ZeroEx: TransformERC20, TokenSpender (#2545)
* `@0x/contracts-utils`: Convert more 0.6 contracts * `@0x/contracts-erc20`: Add solidity 0.6 contracts. * `@0x/utils`: Add new `ZeroExRevertErrors` revert types * `@0x/contracts-zero-ex`: Introduce the `TransformERC20` feature. * `@0x/subproviders`: Update ganache-core. `@0x/web3-wrapper`: Update ganache-core. * `@0x/contracts-zero-ex`: Make `TokenSpender`'s puppet contract a distinct contract type and rename `getTokenSpenderPuppet()` to `getAllowanceTarget()` * `@0x/zero-ex`: Rebase and use "slot" instead of "offset" language in storage buckets. * `@0x/web3-wrapper`: Add `getAccountNonceAsync()` to `Web3Wrapper` * `@0x/contracts-zero-ex`: Revamp TransformERC20. * `@0x/contracts-zero-ex`: Remove `payable` from `IERC20Transformer.transform()` and disable hex capitalization linter rule because of prettier conflicts. * `@0x/contracts-zero-ex`: Use `immutable` owner in `Puppet` instead of `Ownable`. * `@x/utils`: Address review feedback. * `@0x/contracts-zero-ex`: Address review feedback. * `@0x/contracts-utils`: Address review feedback. * `@0x/contracts-zero-ex`: Return deployment nonce in `transform()`. * `@0x/contracts-zero-ex`: Finish returning deployment nonce in `transform()`. * `@0x/contracts-zero-ex`: Fix doc-gen bug. * `@0x/contracts-zero-ex`: Address review comments. * `@0x/utils`: Add `NegativeTransformERC20OutputERror` * `@0x/contracts-zero-ex`: Revert if the taker's output amount decreases. Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
parent
b23f1eb145
commit
2fce332ed7
@ -5,6 +5,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add `LibERC20Token.approveIfBelow()`",
|
"note": "Add `LibERC20Token.approveIfBelow()`",
|
||||||
"pr": 2512
|
"pr": 2512
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add solidity 0.6 contracts",
|
||||||
|
"pr": 2545
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
95
contracts/erc20/contracts/src/v06/IERC20TokenV06.sol
Normal file
95
contracts/erc20/contracts/src/v06/IERC20TokenV06.sol
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
interface IERC20TokenV06 {
|
||||||
|
|
||||||
|
// solhint-disable no-simple-event-func-name
|
||||||
|
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);
|
||||||
|
}
|
32
contracts/erc20/contracts/src/v06/IEtherTokenV06.sol
Normal file
32
contracts/erc20/contracts/src/v06/IEtherTokenV06.sol
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
import "./IERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
interface IEtherTokenV06 is
|
||||||
|
IERC20TokenV06
|
||||||
|
{
|
||||||
|
/// @dev Wrap ether.
|
||||||
|
function deposit() external payable;
|
||||||
|
|
||||||
|
/// @dev Unwrap ether.
|
||||||
|
function withdraw(uint256 amount) external;
|
||||||
|
}
|
212
contracts/erc20/contracts/src/v06/LibERC20TokenV06.sol
Normal file
212
contracts/erc20/contracts/src/v06/LibERC20TokenV06.sol
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
|
||||||
|
import "./IERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
library LibERC20TokenV06 {
|
||||||
|
bytes constant private DECIMALS_CALL_DATA = hex"313ce567";
|
||||||
|
|
||||||
|
/// @dev Calls `IERC20TokenV06(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 compatApprove(
|
||||||
|
IERC20TokenV06 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
|
||||||
|
/// 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(
|
||||||
|
IERC20TokenV06 token,
|
||||||
|
address spender,
|
||||||
|
uint256 amount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
if (token.allowance(address(this), spender) < amount) {
|
||||||
|
compatApprove(token, spender, uint256(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Calls `IERC20TokenV06(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 compatTransfer(
|
||||||
|
IERC20TokenV06 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()`.
|
||||||
|
/// 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 compatTransferFrom(
|
||||||
|
IERC20TokenV06 token,
|
||||||
|
address from,
|
||||||
|
address to,
|
||||||
|
uint256 amount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
bytes memory callData = abi.encodeWithSelector(
|
||||||
|
token.transferFrom.selector,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
amount
|
||||||
|
);
|
||||||
|
_callWithOptionalBooleanResult(address(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 compatDecimals(IERC20TokenV06 token)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (uint8 tokenDecimals)
|
||||||
|
{
|
||||||
|
tokenDecimals = 18;
|
||||||
|
(bool didSucceed, bytes memory resultData) = address(token).staticcall(DECIMALS_CALL_DATA);
|
||||||
|
if (didSucceed && resultData.length == 32) {
|
||||||
|
tokenDecimals = uint8(LibBytesV06.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 compatAllowance(IERC20TokenV06 token, address owner, address spender)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (uint256 allowance_)
|
||||||
|
{
|
||||||
|
(bool didSucceed, bytes memory resultData) = address(token).staticcall(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
token.allowance.selector,
|
||||||
|
owner,
|
||||||
|
spender
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (didSucceed && resultData.length == 32) {
|
||||||
|
allowance_ = LibBytesV06.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 compatBalanceOf(IERC20TokenV06 token, address owner)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (uint256 balance)
|
||||||
|
{
|
||||||
|
(bool didSucceed, bytes memory resultData) = address(token).staticcall(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
token.balanceOf.selector,
|
||||||
|
owner
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (didSucceed && resultData.length == 32) {
|
||||||
|
balance = LibBytesV06.readUint256(resultData, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Check if the data returned by a non-static call to an ERC20 token
|
||||||
|
/// is a successful result. Supported functions are `transfer()`,
|
||||||
|
/// `transferFrom()`, and `approve()`.
|
||||||
|
/// @param resultData The raw data returned by a non-static call to the ERC20 token.
|
||||||
|
/// @return isSuccessful Whether the result data indicates success.
|
||||||
|
function isSuccessfulResult(bytes memory resultData)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bool isSuccessful)
|
||||||
|
{
|
||||||
|
if (resultData.length == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (resultData.length == 32) {
|
||||||
|
uint256 result = LibBytesV06.readUint256(resultData, 0);
|
||||||
|
if (result == 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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 && isSuccessfulResult(resultData)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LibRichErrorsV06.rrevert(resultData);
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "DummyERC20Token,ERC20Token,WETH9,ZRXToken,DummyNoReturnERC20Token,DummyMultipleReturnERC20Token",
|
"publicInterfaceContracts": "DummyERC20Token,ERC20Token,WETH9,ZRXToken,DummyNoReturnERC20Token,DummyMultipleReturnERC20Token",
|
||||||
"abis": "./test/generated-artifacts/@(DummyERC20Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|IERC20Token|IEtherToken|LibERC20Token|MintableERC20Token|TestLibERC20Token|TestLibERC20TokenTarget|UnlimitedAllowanceERC20Token|UntransferrableDummyERC20Token|WETH9|ZRXToken).json",
|
"abis": "./test/generated-artifacts/@(DummyERC20Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|IERC20Token|IERC20TokenV06|IEtherToken|IEtherTokenV06|LibERC20Token|LibERC20TokenV06|MintableERC20Token|TestLibERC20Token|TestLibERC20TokenTarget|UnlimitedAllowanceERC20Token|UntransferrableDummyERC20Token|WETH9|ZRXToken).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -10,8 +10,11 @@ import * as DummyMultipleReturnERC20Token from '../test/generated-artifacts/Dumm
|
|||||||
import * as DummyNoReturnERC20Token from '../test/generated-artifacts/DummyNoReturnERC20Token.json';
|
import * as DummyNoReturnERC20Token from '../test/generated-artifacts/DummyNoReturnERC20Token.json';
|
||||||
import * as ERC20Token from '../test/generated-artifacts/ERC20Token.json';
|
import * as ERC20Token from '../test/generated-artifacts/ERC20Token.json';
|
||||||
import * as IERC20Token from '../test/generated-artifacts/IERC20Token.json';
|
import * as IERC20Token from '../test/generated-artifacts/IERC20Token.json';
|
||||||
|
import * as IERC20TokenV06 from '../test/generated-artifacts/IERC20TokenV06.json';
|
||||||
import * as IEtherToken from '../test/generated-artifacts/IEtherToken.json';
|
import * as IEtherToken from '../test/generated-artifacts/IEtherToken.json';
|
||||||
|
import * as IEtherTokenV06 from '../test/generated-artifacts/IEtherTokenV06.json';
|
||||||
import * as LibERC20Token from '../test/generated-artifacts/LibERC20Token.json';
|
import * as LibERC20Token from '../test/generated-artifacts/LibERC20Token.json';
|
||||||
|
import * as LibERC20TokenV06 from '../test/generated-artifacts/LibERC20TokenV06.json';
|
||||||
import * as MintableERC20Token from '../test/generated-artifacts/MintableERC20Token.json';
|
import * as MintableERC20Token from '../test/generated-artifacts/MintableERC20Token.json';
|
||||||
import * as TestLibERC20Token from '../test/generated-artifacts/TestLibERC20Token.json';
|
import * as TestLibERC20Token from '../test/generated-artifacts/TestLibERC20Token.json';
|
||||||
import * as TestLibERC20TokenTarget from '../test/generated-artifacts/TestLibERC20TokenTarget.json';
|
import * as TestLibERC20TokenTarget from '../test/generated-artifacts/TestLibERC20TokenTarget.json';
|
||||||
@ -28,6 +31,9 @@ export const artifacts = {
|
|||||||
ZRXToken: (ZRXToken as any) as ContractArtifact,
|
ZRXToken: (ZRXToken as any) as ContractArtifact,
|
||||||
IERC20Token: IERC20Token as ContractArtifact,
|
IERC20Token: IERC20Token as ContractArtifact,
|
||||||
IEtherToken: IEtherToken as ContractArtifact,
|
IEtherToken: IEtherToken as ContractArtifact,
|
||||||
|
IERC20TokenV06: IERC20TokenV06 as ContractArtifact,
|
||||||
|
IEtherTokenV06: IEtherTokenV06 as ContractArtifact,
|
||||||
|
LibERC20TokenV06: LibERC20TokenV06 as ContractArtifact,
|
||||||
DummyERC20Token: DummyERC20Token as ContractArtifact,
|
DummyERC20Token: DummyERC20Token as ContractArtifact,
|
||||||
DummyMultipleReturnERC20Token: DummyMultipleReturnERC20Token as ContractArtifact,
|
DummyMultipleReturnERC20Token: DummyMultipleReturnERC20Token as ContractArtifact,
|
||||||
DummyNoReturnERC20Token: DummyNoReturnERC20Token as ContractArtifact,
|
DummyNoReturnERC20Token: DummyNoReturnERC20Token as ContractArtifact,
|
||||||
|
@ -8,8 +8,11 @@ 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/dummy_no_return_erc20_token';
|
||||||
export * from '../test/generated-wrappers/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';
|
||||||
|
export * from '../test/generated-wrappers/i_erc20_token_v06';
|
||||||
export * from '../test/generated-wrappers/i_ether_token';
|
export * from '../test/generated-wrappers/i_ether_token';
|
||||||
|
export * from '../test/generated-wrappers/i_ether_token_v06';
|
||||||
export * from '../test/generated-wrappers/lib_erc20_token';
|
export * from '../test/generated-wrappers/lib_erc20_token';
|
||||||
|
export * from '../test/generated-wrappers/lib_erc20_token_v06';
|
||||||
export * from '../test/generated-wrappers/mintable_erc20_token';
|
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';
|
||||||
export * from '../test/generated-wrappers/test_lib_erc20_token_target';
|
export * from '../test/generated-wrappers/test_lib_erc20_token_target';
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
"test/generated-artifacts/DummyNoReturnERC20Token.json",
|
"test/generated-artifacts/DummyNoReturnERC20Token.json",
|
||||||
"test/generated-artifacts/ERC20Token.json",
|
"test/generated-artifacts/ERC20Token.json",
|
||||||
"test/generated-artifacts/IERC20Token.json",
|
"test/generated-artifacts/IERC20Token.json",
|
||||||
|
"test/generated-artifacts/IERC20TokenV06.json",
|
||||||
"test/generated-artifacts/IEtherToken.json",
|
"test/generated-artifacts/IEtherToken.json",
|
||||||
|
"test/generated-artifacts/IEtherTokenV06.json",
|
||||||
"test/generated-artifacts/LibERC20Token.json",
|
"test/generated-artifacts/LibERC20Token.json",
|
||||||
|
"test/generated-artifacts/LibERC20TokenV06.json",
|
||||||
"test/generated-artifacts/MintableERC20Token.json",
|
"test/generated-artifacts/MintableERC20Token.json",
|
||||||
"test/generated-artifacts/TestLibERC20Token.json",
|
"test/generated-artifacts/TestLibERC20Token.json",
|
||||||
"test/generated-artifacts/TestLibERC20TokenTarget.json",
|
"test/generated-artifacts/TestLibERC20TokenTarget.json",
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add solidity 0.6 contracts",
|
"note": "Add solidity 0.6 contracts",
|
||||||
"pr": 2540
|
"pr": 2540
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add more solidity 0.6 contracts",
|
||||||
|
"pr": 2545
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
166
contracts/utils/contracts/src/v06/AuthorizableV06.sol
Normal file
166
contracts/utils/contracts/src/v06/AuthorizableV06.sol
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
import "./interfaces/IAuthorizableV06.sol";
|
||||||
|
import "./errors/LibRichErrorsV06.sol";
|
||||||
|
import "./errors/LibAuthorizableRichErrorsV06.sol";
|
||||||
|
import "./OwnableV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// solhint-disable no-empty-blocks
|
||||||
|
contract AuthorizableV06 is
|
||||||
|
OwnableV06,
|
||||||
|
IAuthorizableV06
|
||||||
|
{
|
||||||
|
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||||
|
modifier onlyAuthorized {
|
||||||
|
_assertSenderIsAuthorized();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Whether an address is authorized to call privileged functions.
|
||||||
|
/// @param 0 Address to query.
|
||||||
|
/// @return 0 Whether the address is authorized.
|
||||||
|
mapping (address => bool) public override authorized;
|
||||||
|
/// @dev Whether an address is authorized to call privileged functions.
|
||||||
|
/// @param 0 Index of authorized address.
|
||||||
|
/// @return 0 Authorized address.
|
||||||
|
address[] public override authorities;
|
||||||
|
|
||||||
|
/// @dev Initializes the `owner` address.
|
||||||
|
constructor()
|
||||||
|
public
|
||||||
|
OwnableV06()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// @dev Authorizes an address.
|
||||||
|
/// @param target Address to authorize.
|
||||||
|
function addAuthorizedAddress(address target)
|
||||||
|
external
|
||||||
|
override
|
||||||
|
onlyOwner
|
||||||
|
{
|
||||||
|
_addAuthorizedAddress(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Removes authorizion of an address.
|
||||||
|
/// @param target Address to remove authorization from.
|
||||||
|
function removeAuthorizedAddress(address target)
|
||||||
|
external
|
||||||
|
override
|
||||||
|
onlyOwner
|
||||||
|
{
|
||||||
|
if (!authorized[target]) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.TargetNotAuthorizedError(target));
|
||||||
|
}
|
||||||
|
for (uint256 i = 0; i < authorities.length; i++) {
|
||||||
|
if (authorities[i] == target) {
|
||||||
|
_removeAuthorizedAddressAtIndex(target, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Removes authorizion of an address.
|
||||||
|
/// @param target Address to remove authorization from.
|
||||||
|
/// @param index Index of target in authorities array.
|
||||||
|
function removeAuthorizedAddressAtIndex(
|
||||||
|
address target,
|
||||||
|
uint256 index
|
||||||
|
)
|
||||||
|
external
|
||||||
|
override
|
||||||
|
onlyOwner
|
||||||
|
{
|
||||||
|
_removeAuthorizedAddressAtIndex(target, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Gets all authorized addresses.
|
||||||
|
/// @return Array of authorized addresses.
|
||||||
|
function getAuthorizedAddresses()
|
||||||
|
external
|
||||||
|
override
|
||||||
|
view
|
||||||
|
returns (address[] memory)
|
||||||
|
{
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Reverts if msg.sender is not authorized.
|
||||||
|
function _assertSenderIsAuthorized()
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
{
|
||||||
|
if (!authorized[msg.sender]) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.SenderNotAuthorizedError(msg.sender));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Authorizes an address.
|
||||||
|
/// @param target Address to authorize.
|
||||||
|
function _addAuthorizedAddress(address target)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
// Ensure that the target is not the zero address.
|
||||||
|
if (target == address(0)) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.ZeroCantBeAuthorizedError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the target is not already authorized.
|
||||||
|
if (authorized[target]) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.TargetAlreadyAuthorizedError(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
authorized[target] = true;
|
||||||
|
authorities.push(target);
|
||||||
|
emit AuthorizedAddressAdded(target, msg.sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Removes authorizion of an address.
|
||||||
|
/// @param target Address to remove authorization from.
|
||||||
|
/// @param index Index of target in authorities array.
|
||||||
|
function _removeAuthorizedAddressAtIndex(
|
||||||
|
address target,
|
||||||
|
uint256 index
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
if (!authorized[target]) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.TargetNotAuthorizedError(target));
|
||||||
|
}
|
||||||
|
if (index >= authorities.length) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.IndexOutOfBoundsError(
|
||||||
|
index,
|
||||||
|
authorities.length
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (authorities[index] != target) {
|
||||||
|
LibRichErrorsV06.rrevert(LibAuthorizableRichErrorsV06.AuthorizedAddressMismatchError(
|
||||||
|
authorities[index],
|
||||||
|
target
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete authorized[target];
|
||||||
|
authorities[index] = authorities[authorities.length - 1];
|
||||||
|
authorities.pop();
|
||||||
|
emit AuthorizedAddressRemoved(target, msg.sender);
|
||||||
|
}
|
||||||
|
}
|
228
contracts/utils/contracts/src/v06/LibMathV06.sol
Normal file
228
contracts/utils/contracts/src/v06/LibMathV06.sol
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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.6.5;
|
||||||
|
|
||||||
|
import "./LibSafeMathV06.sol";
|
||||||
|
import "./errors/LibRichErrorsV06.sol";
|
||||||
|
import "./errors/LibMathRichErrorsV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
library LibMathV06 {
|
||||||
|
|
||||||
|
using LibSafeMathV06 for uint256;
|
||||||
|
|
||||||
|
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||||
|
/// Reverts if rounding error is >= 0.1%
|
||||||
|
/// @param numerator Numerator.
|
||||||
|
/// @param denominator Denominator.
|
||||||
|
/// @param target Value to calculate partial of.
|
||||||
|
/// @return partialAmount Partial value of target rounded down.
|
||||||
|
function safeGetPartialAmountFloor(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256 partialAmount)
|
||||||
|
{
|
||||||
|
if (isRoundingErrorFloor(
|
||||||
|
numerator,
|
||||||
|
denominator,
|
||||||
|
target
|
||||||
|
)) {
|
||||||
|
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.RoundingError(
|
||||||
|
numerator,
|
||||||
|
denominator,
|
||||||
|
target
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||||
|
return partialAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||||
|
/// Reverts if rounding error is >= 0.1%
|
||||||
|
/// @param numerator Numerator.
|
||||||
|
/// @param denominator Denominator.
|
||||||
|
/// @param target Value to calculate partial of.
|
||||||
|
/// @return partialAmount Partial value of target rounded up.
|
||||||
|
function safeGetPartialAmountCeil(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256 partialAmount)
|
||||||
|
{
|
||||||
|
if (isRoundingErrorCeil(
|
||||||
|
numerator,
|
||||||
|
denominator,
|
||||||
|
target
|
||||||
|
)) {
|
||||||
|
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.RoundingError(
|
||||||
|
numerator,
|
||||||
|
denominator,
|
||||||
|
target
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
|
||||||
|
// ceil(a / b) = floor((a + b - 1) / b)
|
||||||
|
// To implement `ceil(a / b)` using safeDiv.
|
||||||
|
partialAmount = numerator.safeMul(target)
|
||||||
|
.safeAdd(denominator.safeSub(1))
|
||||||
|
.safeDiv(denominator);
|
||||||
|
|
||||||
|
return partialAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||||
|
/// @param numerator Numerator.
|
||||||
|
/// @param denominator Denominator.
|
||||||
|
/// @param target Value to calculate partial of.
|
||||||
|
/// @return partialAmount Partial value of target rounded down.
|
||||||
|
function getPartialAmountFloor(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256 partialAmount)
|
||||||
|
{
|
||||||
|
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||||
|
return partialAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||||
|
/// @param numerator Numerator.
|
||||||
|
/// @param denominator Denominator.
|
||||||
|
/// @param target Value to calculate partial of.
|
||||||
|
/// @return partialAmount Partial value of target rounded up.
|
||||||
|
function getPartialAmountCeil(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256 partialAmount)
|
||||||
|
{
|
||||||
|
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
|
||||||
|
// ceil(a / b) = floor((a + b - 1) / b)
|
||||||
|
// To implement `ceil(a / b)` using safeDiv.
|
||||||
|
partialAmount = numerator.safeMul(target)
|
||||||
|
.safeAdd(denominator.safeSub(1))
|
||||||
|
.safeDiv(denominator);
|
||||||
|
|
||||||
|
return partialAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Checks if rounding error >= 0.1% when rounding down.
|
||||||
|
/// @param numerator Numerator.
|
||||||
|
/// @param denominator Denominator.
|
||||||
|
/// @param target Value to multiply with numerator/denominator.
|
||||||
|
/// @return isError Rounding error is present.
|
||||||
|
function isRoundingErrorFloor(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bool isError)
|
||||||
|
{
|
||||||
|
if (denominator == 0) {
|
||||||
|
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.DivisionByZeroError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// The absolute rounding error is the difference between the rounded
|
||||||
|
// value and the ideal value. The relative rounding error is the
|
||||||
|
// absolute rounding error divided by the absolute value of the
|
||||||
|
// ideal value. This is undefined when the ideal value is zero.
|
||||||
|
//
|
||||||
|
// The ideal value is `numerator * target / denominator`.
|
||||||
|
// Let's call `numerator * target % denominator` the remainder.
|
||||||
|
// The absolute error is `remainder / denominator`.
|
||||||
|
//
|
||||||
|
// When the ideal value is zero, we require the absolute error to
|
||||||
|
// be zero. Fortunately, this is always the case. The ideal value is
|
||||||
|
// zero iff `numerator == 0` and/or `target == 0`. In this case the
|
||||||
|
// remainder and absolute error are also zero.
|
||||||
|
if (target == 0 || numerator == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we want the relative rounding error to be strictly
|
||||||
|
// less than 0.1%.
|
||||||
|
// The relative error is `remainder / (numerator * target)`.
|
||||||
|
// We want the relative error less than 1 / 1000:
|
||||||
|
// remainder / (numerator * denominator) < 1 / 1000
|
||||||
|
// or equivalently:
|
||||||
|
// 1000 * remainder < numerator * target
|
||||||
|
// so we have a rounding error iff:
|
||||||
|
// 1000 * remainder >= numerator * target
|
||||||
|
uint256 remainder = mulmod(
|
||||||
|
target,
|
||||||
|
numerator,
|
||||||
|
denominator
|
||||||
|
);
|
||||||
|
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||||
|
return isError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Checks if rounding error >= 0.1% when rounding up.
|
||||||
|
/// @param numerator Numerator.
|
||||||
|
/// @param denominator Denominator.
|
||||||
|
/// @param target Value to multiply with numerator/denominator.
|
||||||
|
/// @return isError Rounding error is present.
|
||||||
|
function isRoundingErrorCeil(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bool isError)
|
||||||
|
{
|
||||||
|
if (denominator == 0) {
|
||||||
|
LibRichErrorsV06.rrevert(LibMathRichErrorsV06.DivisionByZeroError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the comments in `isRoundingError`.
|
||||||
|
if (target == 0 || numerator == 0) {
|
||||||
|
// When either is zero, the ideal value and rounded value are zero
|
||||||
|
// and there is no rounding error. (Although the relative error
|
||||||
|
// is undefined.)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Compute remainder as before
|
||||||
|
uint256 remainder = mulmod(
|
||||||
|
target,
|
||||||
|
numerator,
|
||||||
|
denominator
|
||||||
|
);
|
||||||
|
remainder = denominator.safeSub(remainder) % denominator;
|
||||||
|
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||||
|
return isError;
|
||||||
|
}
|
||||||
|
}
|
108
contracts/utils/contracts/src/v06/LibSafeMathV06.sol
Normal file
108
contracts/utils/contracts/src/v06/LibSafeMathV06.sol
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
import "./errors/LibRichErrorsV06.sol";
|
||||||
|
import "./errors/LibSafeMathRichErrorsV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
library LibSafeMathV06 {
|
||||||
|
|
||||||
|
function safeMul(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
if (a == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint256 c = a * b;
|
||||||
|
if (c / a != b) {
|
||||||
|
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||||
|
LibSafeMathRichErrorsV06.BinOpErrorCodes.MULTIPLICATION_OVERFLOW,
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeDiv(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
if (b == 0) {
|
||||||
|
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||||
|
LibSafeMathRichErrorsV06.BinOpErrorCodes.DIVISION_BY_ZERO,
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
));
|
||||||
|
}
|
||||||
|
uint256 c = a / b;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeSub(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
if (b > a) {
|
||||||
|
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||||
|
LibSafeMathRichErrorsV06.BinOpErrorCodes.SUBTRACTION_UNDERFLOW,
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeAdd(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
uint256 c = a + b;
|
||||||
|
if (c < a) {
|
||||||
|
LibRichErrorsV06.rrevert(LibSafeMathRichErrorsV06.Uint256BinOpError(
|
||||||
|
LibSafeMathRichErrorsV06.BinOpErrorCodes.ADDITION_OVERFLOW,
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function max256(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return a >= b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function min256(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
}
|
68
contracts/utils/contracts/src/v06/OwnableV06.sol
Normal file
68
contracts/utils/contracts/src/v06/OwnableV06.sol
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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.6.5;
|
||||||
|
|
||||||
|
import "./interfaces/IOwnableV06.sol";
|
||||||
|
import "./errors/LibRichErrorsV06.sol";
|
||||||
|
import "./errors/LibOwnableRichErrorsV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract OwnableV06 is
|
||||||
|
IOwnableV06
|
||||||
|
{
|
||||||
|
/// @dev The owner of this contract.
|
||||||
|
/// @return 0 The owner address.
|
||||||
|
address public override owner;
|
||||||
|
|
||||||
|
constructor() public {
|
||||||
|
owner = msg.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier onlyOwner() {
|
||||||
|
_assertSenderIsOwner();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Change the owner of this contract.
|
||||||
|
/// @param newOwner New owner address.
|
||||||
|
function transferOwnership(address newOwner)
|
||||||
|
public
|
||||||
|
override
|
||||||
|
onlyOwner
|
||||||
|
{
|
||||||
|
if (newOwner == address(0)) {
|
||||||
|
LibRichErrorsV06.rrevert(LibOwnableRichErrorsV06.TransferOwnerToZeroError());
|
||||||
|
} else {
|
||||||
|
owner = newOwner;
|
||||||
|
emit OwnershipTransferred(msg.sender, newOwner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _assertSenderIsOwner()
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
{
|
||||||
|
if (msg.sender != owner) {
|
||||||
|
LibRichErrorsV06.rrevert(LibOwnableRichErrorsV06.OnlyOwnerError(
|
||||||
|
msg.sender,
|
||||||
|
owner
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
contracts/utils/contracts/src/v06/ReentrancyGuardV06.sol
Normal file
57
contracts/utils/contracts/src/v06/ReentrancyGuardV06.sol
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
import "./errors/LibReentrancyGuardRichErrorsV06.sol";
|
||||||
|
import "./errors/LibRichErrorsV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract ReentrancyGuardV06 {
|
||||||
|
|
||||||
|
// Locked state of mutex.
|
||||||
|
bool private _locked = false;
|
||||||
|
|
||||||
|
/// @dev Functions with this modifer cannot be reentered. The mutex will be locked
|
||||||
|
/// before function execution and unlocked after.
|
||||||
|
modifier nonReentrant() {
|
||||||
|
_lockMutexOrThrowIfAlreadyLocked();
|
||||||
|
_;
|
||||||
|
_unlockMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lockMutexOrThrowIfAlreadyLocked()
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
// Ensure mutex is unlocked.
|
||||||
|
if (_locked) {
|
||||||
|
LibRichErrorsV06.rrevert(
|
||||||
|
LibReentrancyGuardRichErrorsV06.IllegalReentrancyError()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Lock mutex.
|
||||||
|
_locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _unlockMutex()
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
// Unlock mutex.
|
||||||
|
_locked = false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibAuthorizableRichErrorsV06 {
|
||||||
|
|
||||||
|
// bytes4(keccak256("AuthorizedAddressMismatchError(address,address)"))
|
||||||
|
bytes4 internal constant AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR =
|
||||||
|
0x140a84db;
|
||||||
|
|
||||||
|
// bytes4(keccak256("IndexOutOfBoundsError(uint256,uint256)"))
|
||||||
|
bytes4 internal constant INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR =
|
||||||
|
0xe9f83771;
|
||||||
|
|
||||||
|
// bytes4(keccak256("SenderNotAuthorizedError(address)"))
|
||||||
|
bytes4 internal constant SENDER_NOT_AUTHORIZED_ERROR_SELECTOR =
|
||||||
|
0xb65a25b9;
|
||||||
|
|
||||||
|
// bytes4(keccak256("TargetAlreadyAuthorizedError(address)"))
|
||||||
|
bytes4 internal constant TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR =
|
||||||
|
0xde16f1a0;
|
||||||
|
|
||||||
|
// bytes4(keccak256("TargetNotAuthorizedError(address)"))
|
||||||
|
bytes4 internal constant TARGET_NOT_AUTHORIZED_ERROR_SELECTOR =
|
||||||
|
0xeb5108a2;
|
||||||
|
|
||||||
|
// bytes4(keccak256("ZeroCantBeAuthorizedError()"))
|
||||||
|
bytes internal constant ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES =
|
||||||
|
hex"57654fe4";
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
function AuthorizedAddressMismatchError(
|
||||||
|
address authorized,
|
||||||
|
address target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR,
|
||||||
|
authorized,
|
||||||
|
target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IndexOutOfBoundsError(
|
||||||
|
uint256 index,
|
||||||
|
uint256 length
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR,
|
||||||
|
index,
|
||||||
|
length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SenderNotAuthorizedError(address sender)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
SENDER_NOT_AUTHORIZED_ERROR_SELECTOR,
|
||||||
|
sender
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TargetAlreadyAuthorizedError(address target)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR,
|
||||||
|
target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TargetNotAuthorizedError(address target)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
TARGET_NOT_AUTHORIZED_ERROR_SELECTOR,
|
||||||
|
target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ZeroCantBeAuthorizedError()
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibMathRichErrorsV06 {
|
||||||
|
|
||||||
|
// bytes4(keccak256("DivisionByZeroError()"))
|
||||||
|
bytes internal constant DIVISION_BY_ZERO_ERROR =
|
||||||
|
hex"a791837c";
|
||||||
|
|
||||||
|
// bytes4(keccak256("RoundingError(uint256,uint256,uint256)"))
|
||||||
|
bytes4 internal constant ROUNDING_ERROR_SELECTOR =
|
||||||
|
0x339f3de2;
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
function DivisionByZeroError()
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return DIVISION_BY_ZERO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RoundingError(
|
||||||
|
uint256 numerator,
|
||||||
|
uint256 denominator,
|
||||||
|
uint256 target
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
ROUNDING_ERROR_SELECTOR,
|
||||||
|
numerator,
|
||||||
|
denominator,
|
||||||
|
target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibOwnableRichErrorsV06 {
|
||||||
|
|
||||||
|
// bytes4(keccak256("OnlyOwnerError(address,address)"))
|
||||||
|
bytes4 internal constant ONLY_OWNER_ERROR_SELECTOR =
|
||||||
|
0x1de45ad1;
|
||||||
|
|
||||||
|
// bytes4(keccak256("TransferOwnerToZeroError()"))
|
||||||
|
bytes internal constant TRANSFER_OWNER_TO_ZERO_ERROR_BYTES =
|
||||||
|
hex"e69edc3e";
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
function OnlyOwnerError(
|
||||||
|
address sender,
|
||||||
|
address owner
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
ONLY_OWNER_ERROR_SELECTOR,
|
||||||
|
sender,
|
||||||
|
owner
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TransferOwnerToZeroError()
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return TRANSFER_OWNER_TO_ZERO_ERROR_BYTES;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibReentrancyGuardRichErrorsV06 {
|
||||||
|
|
||||||
|
// bytes4(keccak256("IllegalReentrancyError()"))
|
||||||
|
bytes internal constant ILLEGAL_REENTRANCY_ERROR_SELECTOR_BYTES =
|
||||||
|
hex"0c3b823f";
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
function IllegalReentrancyError()
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return ILLEGAL_REENTRANCY_ERROR_SELECTOR_BYTES;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibSafeMathRichErrorsV06 {
|
||||||
|
|
||||||
|
// bytes4(keccak256("Uint256BinOpError(uint8,uint256,uint256)"))
|
||||||
|
bytes4 internal constant UINT256_BINOP_ERROR_SELECTOR =
|
||||||
|
0xe946c1bb;
|
||||||
|
|
||||||
|
// bytes4(keccak256("Uint256DowncastError(uint8,uint256)"))
|
||||||
|
bytes4 internal constant UINT256_DOWNCAST_ERROR_SELECTOR =
|
||||||
|
0xc996af7b;
|
||||||
|
|
||||||
|
enum BinOpErrorCodes {
|
||||||
|
ADDITION_OVERFLOW,
|
||||||
|
MULTIPLICATION_OVERFLOW,
|
||||||
|
SUBTRACTION_UNDERFLOW,
|
||||||
|
DIVISION_BY_ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DowncastErrorCodes {
|
||||||
|
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT32,
|
||||||
|
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT64,
|
||||||
|
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT96
|
||||||
|
}
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
function Uint256BinOpError(
|
||||||
|
BinOpErrorCodes errorCode,
|
||||||
|
uint256 a,
|
||||||
|
uint256 b
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
UINT256_BINOP_ERROR_SELECTOR,
|
||||||
|
errorCode,
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Uint256DowncastError(
|
||||||
|
DowncastErrorCodes errorCode,
|
||||||
|
uint256 a
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
UINT256_DOWNCAST_ERROR_SELECTOR,
|
||||||
|
errorCode,
|
||||||
|
a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
import "./IOwnableV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
interface IAuthorizableV06 is
|
||||||
|
IOwnableV06
|
||||||
|
{
|
||||||
|
// Event logged when a new address is authorized.
|
||||||
|
event AuthorizedAddressAdded(
|
||||||
|
address indexed target,
|
||||||
|
address indexed caller
|
||||||
|
);
|
||||||
|
|
||||||
|
// Event logged when a currently authorized address is unauthorized.
|
||||||
|
event AuthorizedAddressRemoved(
|
||||||
|
address indexed target,
|
||||||
|
address indexed caller
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @dev Authorizes an address.
|
||||||
|
/// @param target Address to authorize.
|
||||||
|
function addAuthorizedAddress(address target)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Removes authorizion of an address.
|
||||||
|
/// @param target Address to remove authorization from.
|
||||||
|
function removeAuthorizedAddress(address target)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Removes authorizion of an address.
|
||||||
|
/// @param target Address to remove authorization from.
|
||||||
|
/// @param index Index of target in authorities array.
|
||||||
|
function removeAuthorizedAddressAtIndex(
|
||||||
|
address target,
|
||||||
|
uint256 index
|
||||||
|
)
|
||||||
|
external;
|
||||||
|
|
||||||
|
/// @dev Gets all authorized addresses.
|
||||||
|
/// @return authorizedAddresses Array of authorized addresses.
|
||||||
|
function getAuthorizedAddresses()
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (address[] memory authorizedAddresses);
|
||||||
|
|
||||||
|
/// @dev Whether an adderss is authorized to call privileged functions.
|
||||||
|
/// @param addr Address to query.
|
||||||
|
/// @return isAuthorized Whether the address is authorized.
|
||||||
|
function authorized(address addr) external view returns (bool isAuthorized);
|
||||||
|
|
||||||
|
/// @dev All addresseses authorized to call privileged functions.
|
||||||
|
/// @param idx Index of authorized address.
|
||||||
|
/// @return addr Authorized address.
|
||||||
|
function authorities(uint256 idx) external view returns (address addr);
|
||||||
|
|
||||||
|
}
|
@ -38,7 +38,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "Authorizable,IAuthorizable,IOwnable,LibAddress,LibAddressArray,LibAddressArrayRichErrors,LibAuthorizableRichErrors,LibBytes,LibBytesRichErrors,LibEIP1271,LibEIP712,LibFractions,LibOwnableRichErrors,LibReentrancyGuardRichErrors,LibRichErrors,LibSafeMath,LibSafeMathRichErrors,Ownable,ReentrancyGuard,Refundable",
|
"publicInterfaceContracts": "Authorizable,IAuthorizable,IOwnable,LibAddress,LibAddressArray,LibAddressArrayRichErrors,LibAuthorizableRichErrors,LibBytes,LibBytesRichErrors,LibEIP1271,LibEIP712,LibFractions,LibOwnableRichErrors,LibReentrancyGuardRichErrors,LibRichErrors,LibSafeMath,LibSafeMathRichErrors,Ownable,ReentrancyGuard,Refundable",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(Authorizable|D18|DeploymentConstants|IAuthorizable|IOwnable|IOwnableV06|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibBytesRichErrorsV06|LibBytesV06|LibEIP1271|LibEIP712|LibFractions|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibRichErrorsV06|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|Refundable|TestAuthorizable|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLibSafeMath|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver).json"
|
"abis": "./test/generated-artifacts/@(Authorizable|AuthorizableV06|D18|DeploymentConstants|IAuthorizable|IAuthorizableV06|IOwnable|IOwnableV06|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibAuthorizableRichErrorsV06|LibBytes|LibBytesRichErrors|LibBytesRichErrorsV06|LibBytesV06|LibEIP1271|LibEIP712|LibFractions|LibMathRichErrorsV06|LibMathV06|LibOwnableRichErrors|LibOwnableRichErrorsV06|LibReentrancyGuardRichErrors|LibReentrancyGuardRichErrorsV06|LibRichErrors|LibRichErrorsV06|LibSafeMath|LibSafeMathRichErrors|LibSafeMathRichErrorsV06|LibSafeMathV06|Ownable|OwnableV06|ReentrancyGuard|ReentrancyGuardV06|Refundable|TestAuthorizable|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLibSafeMath|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -6,15 +6,18 @@
|
|||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
import * as Authorizable from '../test/generated-artifacts/Authorizable.json';
|
import * as Authorizable from '../test/generated-artifacts/Authorizable.json';
|
||||||
|
import * as AuthorizableV06 from '../test/generated-artifacts/AuthorizableV06.json';
|
||||||
import * as D18 from '../test/generated-artifacts/D18.json';
|
import * as D18 from '../test/generated-artifacts/D18.json';
|
||||||
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
|
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
|
||||||
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
|
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
|
||||||
|
import * as IAuthorizableV06 from '../test/generated-artifacts/IAuthorizableV06.json';
|
||||||
import * as IOwnable from '../test/generated-artifacts/IOwnable.json';
|
import * as IOwnable from '../test/generated-artifacts/IOwnable.json';
|
||||||
import * as IOwnableV06 from '../test/generated-artifacts/IOwnableV06.json';
|
import * as IOwnableV06 from '../test/generated-artifacts/IOwnableV06.json';
|
||||||
import * as LibAddress from '../test/generated-artifacts/LibAddress.json';
|
import * as LibAddress from '../test/generated-artifacts/LibAddress.json';
|
||||||
import * as LibAddressArray from '../test/generated-artifacts/LibAddressArray.json';
|
import * as LibAddressArray from '../test/generated-artifacts/LibAddressArray.json';
|
||||||
import * as LibAddressArrayRichErrors from '../test/generated-artifacts/LibAddressArrayRichErrors.json';
|
import * as LibAddressArrayRichErrors from '../test/generated-artifacts/LibAddressArrayRichErrors.json';
|
||||||
import * as LibAuthorizableRichErrors from '../test/generated-artifacts/LibAuthorizableRichErrors.json';
|
import * as LibAuthorizableRichErrors from '../test/generated-artifacts/LibAuthorizableRichErrors.json';
|
||||||
|
import * as LibAuthorizableRichErrorsV06 from '../test/generated-artifacts/LibAuthorizableRichErrorsV06.json';
|
||||||
import * as LibBytes from '../test/generated-artifacts/LibBytes.json';
|
import * as LibBytes from '../test/generated-artifacts/LibBytes.json';
|
||||||
import * as LibBytesRichErrors from '../test/generated-artifacts/LibBytesRichErrors.json';
|
import * as LibBytesRichErrors from '../test/generated-artifacts/LibBytesRichErrors.json';
|
||||||
import * as LibBytesRichErrorsV06 from '../test/generated-artifacts/LibBytesRichErrorsV06.json';
|
import * as LibBytesRichErrorsV06 from '../test/generated-artifacts/LibBytesRichErrorsV06.json';
|
||||||
@ -22,14 +25,22 @@ import * as LibBytesV06 from '../test/generated-artifacts/LibBytesV06.json';
|
|||||||
import * as LibEIP1271 from '../test/generated-artifacts/LibEIP1271.json';
|
import * as LibEIP1271 from '../test/generated-artifacts/LibEIP1271.json';
|
||||||
import * as LibEIP712 from '../test/generated-artifacts/LibEIP712.json';
|
import * as LibEIP712 from '../test/generated-artifacts/LibEIP712.json';
|
||||||
import * as LibFractions from '../test/generated-artifacts/LibFractions.json';
|
import * as LibFractions from '../test/generated-artifacts/LibFractions.json';
|
||||||
|
import * as LibMathRichErrorsV06 from '../test/generated-artifacts/LibMathRichErrorsV06.json';
|
||||||
|
import * as LibMathV06 from '../test/generated-artifacts/LibMathV06.json';
|
||||||
import * as LibOwnableRichErrors from '../test/generated-artifacts/LibOwnableRichErrors.json';
|
import * as LibOwnableRichErrors from '../test/generated-artifacts/LibOwnableRichErrors.json';
|
||||||
|
import * as LibOwnableRichErrorsV06 from '../test/generated-artifacts/LibOwnableRichErrorsV06.json';
|
||||||
import * as LibReentrancyGuardRichErrors from '../test/generated-artifacts/LibReentrancyGuardRichErrors.json';
|
import * as LibReentrancyGuardRichErrors from '../test/generated-artifacts/LibReentrancyGuardRichErrors.json';
|
||||||
|
import * as LibReentrancyGuardRichErrorsV06 from '../test/generated-artifacts/LibReentrancyGuardRichErrorsV06.json';
|
||||||
import * as LibRichErrors from '../test/generated-artifacts/LibRichErrors.json';
|
import * as LibRichErrors from '../test/generated-artifacts/LibRichErrors.json';
|
||||||
import * as LibRichErrorsV06 from '../test/generated-artifacts/LibRichErrorsV06.json';
|
import * as LibRichErrorsV06 from '../test/generated-artifacts/LibRichErrorsV06.json';
|
||||||
import * as LibSafeMath from '../test/generated-artifacts/LibSafeMath.json';
|
import * as LibSafeMath from '../test/generated-artifacts/LibSafeMath.json';
|
||||||
import * as LibSafeMathRichErrors from '../test/generated-artifacts/LibSafeMathRichErrors.json';
|
import * as LibSafeMathRichErrors from '../test/generated-artifacts/LibSafeMathRichErrors.json';
|
||||||
|
import * as LibSafeMathRichErrorsV06 from '../test/generated-artifacts/LibSafeMathRichErrorsV06.json';
|
||||||
|
import * as LibSafeMathV06 from '../test/generated-artifacts/LibSafeMathV06.json';
|
||||||
import * as Ownable from '../test/generated-artifacts/Ownable.json';
|
import * as Ownable from '../test/generated-artifacts/Ownable.json';
|
||||||
|
import * as OwnableV06 from '../test/generated-artifacts/OwnableV06.json';
|
||||||
import * as ReentrancyGuard from '../test/generated-artifacts/ReentrancyGuard.json';
|
import * as ReentrancyGuard from '../test/generated-artifacts/ReentrancyGuard.json';
|
||||||
|
import * as ReentrancyGuardV06 from '../test/generated-artifacts/ReentrancyGuardV06.json';
|
||||||
import * as Refundable from '../test/generated-artifacts/Refundable.json';
|
import * as Refundable from '../test/generated-artifacts/Refundable.json';
|
||||||
import * as TestAuthorizable from '../test/generated-artifacts/TestAuthorizable.json';
|
import * as TestAuthorizable from '../test/generated-artifacts/TestAuthorizable.json';
|
||||||
import * as TestLibAddress from '../test/generated-artifacts/TestLibAddress.json';
|
import * as TestLibAddress from '../test/generated-artifacts/TestLibAddress.json';
|
||||||
@ -67,9 +78,20 @@ export const artifacts = {
|
|||||||
Refundable: Refundable as ContractArtifact,
|
Refundable: Refundable as ContractArtifact,
|
||||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||||
IOwnable: IOwnable as ContractArtifact,
|
IOwnable: IOwnable as ContractArtifact,
|
||||||
|
AuthorizableV06: AuthorizableV06 as ContractArtifact,
|
||||||
LibBytesV06: LibBytesV06 as ContractArtifact,
|
LibBytesV06: LibBytesV06 as ContractArtifact,
|
||||||
|
LibMathV06: LibMathV06 as ContractArtifact,
|
||||||
|
LibSafeMathV06: LibSafeMathV06 as ContractArtifact,
|
||||||
|
OwnableV06: OwnableV06 as ContractArtifact,
|
||||||
|
ReentrancyGuardV06: ReentrancyGuardV06 as ContractArtifact,
|
||||||
|
LibAuthorizableRichErrorsV06: LibAuthorizableRichErrorsV06 as ContractArtifact,
|
||||||
LibBytesRichErrorsV06: LibBytesRichErrorsV06 as ContractArtifact,
|
LibBytesRichErrorsV06: LibBytesRichErrorsV06 as ContractArtifact,
|
||||||
|
LibMathRichErrorsV06: LibMathRichErrorsV06 as ContractArtifact,
|
||||||
|
LibOwnableRichErrorsV06: LibOwnableRichErrorsV06 as ContractArtifact,
|
||||||
|
LibReentrancyGuardRichErrorsV06: LibReentrancyGuardRichErrorsV06 as ContractArtifact,
|
||||||
LibRichErrorsV06: LibRichErrorsV06 as ContractArtifact,
|
LibRichErrorsV06: LibRichErrorsV06 as ContractArtifact,
|
||||||
|
LibSafeMathRichErrorsV06: LibSafeMathRichErrorsV06 as ContractArtifact,
|
||||||
|
IAuthorizableV06: IAuthorizableV06 as ContractArtifact,
|
||||||
IOwnableV06: IOwnableV06 as ContractArtifact,
|
IOwnableV06: IOwnableV06 as ContractArtifact,
|
||||||
TestAuthorizable: TestAuthorizable as ContractArtifact,
|
TestAuthorizable: TestAuthorizable as ContractArtifact,
|
||||||
TestLibAddress: TestLibAddress as ContractArtifact,
|
TestLibAddress: TestLibAddress as ContractArtifact,
|
||||||
|
@ -4,15 +4,18 @@
|
|||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export * from '../test/generated-wrappers/authorizable';
|
export * from '../test/generated-wrappers/authorizable';
|
||||||
|
export * from '../test/generated-wrappers/authorizable_v06';
|
||||||
export * from '../test/generated-wrappers/d18';
|
export * from '../test/generated-wrappers/d18';
|
||||||
export * from '../test/generated-wrappers/deployment_constants';
|
export * from '../test/generated-wrappers/deployment_constants';
|
||||||
export * from '../test/generated-wrappers/i_authorizable';
|
export * from '../test/generated-wrappers/i_authorizable';
|
||||||
|
export * from '../test/generated-wrappers/i_authorizable_v06';
|
||||||
export * from '../test/generated-wrappers/i_ownable';
|
export * from '../test/generated-wrappers/i_ownable';
|
||||||
export * from '../test/generated-wrappers/i_ownable_v06';
|
export * from '../test/generated-wrappers/i_ownable_v06';
|
||||||
export * from '../test/generated-wrappers/lib_address';
|
export * from '../test/generated-wrappers/lib_address';
|
||||||
export * from '../test/generated-wrappers/lib_address_array';
|
export * from '../test/generated-wrappers/lib_address_array';
|
||||||
export * from '../test/generated-wrappers/lib_address_array_rich_errors';
|
export * from '../test/generated-wrappers/lib_address_array_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_authorizable_rich_errors';
|
export * from '../test/generated-wrappers/lib_authorizable_rich_errors';
|
||||||
|
export * from '../test/generated-wrappers/lib_authorizable_rich_errors_v06';
|
||||||
export * from '../test/generated-wrappers/lib_bytes';
|
export * from '../test/generated-wrappers/lib_bytes';
|
||||||
export * from '../test/generated-wrappers/lib_bytes_rich_errors';
|
export * from '../test/generated-wrappers/lib_bytes_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_bytes_rich_errors_v06';
|
export * from '../test/generated-wrappers/lib_bytes_rich_errors_v06';
|
||||||
@ -20,14 +23,22 @@ export * from '../test/generated-wrappers/lib_bytes_v06';
|
|||||||
export * from '../test/generated-wrappers/lib_e_i_p1271';
|
export * from '../test/generated-wrappers/lib_e_i_p1271';
|
||||||
export * from '../test/generated-wrappers/lib_e_i_p712';
|
export * from '../test/generated-wrappers/lib_e_i_p712';
|
||||||
export * from '../test/generated-wrappers/lib_fractions';
|
export * from '../test/generated-wrappers/lib_fractions';
|
||||||
|
export * from '../test/generated-wrappers/lib_math_rich_errors_v06';
|
||||||
|
export * from '../test/generated-wrappers/lib_math_v06';
|
||||||
export * from '../test/generated-wrappers/lib_ownable_rich_errors';
|
export * from '../test/generated-wrappers/lib_ownable_rich_errors';
|
||||||
|
export * from '../test/generated-wrappers/lib_ownable_rich_errors_v06';
|
||||||
export * from '../test/generated-wrappers/lib_reentrancy_guard_rich_errors';
|
export * from '../test/generated-wrappers/lib_reentrancy_guard_rich_errors';
|
||||||
|
export * from '../test/generated-wrappers/lib_reentrancy_guard_rich_errors_v06';
|
||||||
export * from '../test/generated-wrappers/lib_rich_errors';
|
export * from '../test/generated-wrappers/lib_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_rich_errors_v06';
|
export * from '../test/generated-wrappers/lib_rich_errors_v06';
|
||||||
export * from '../test/generated-wrappers/lib_safe_math';
|
export * from '../test/generated-wrappers/lib_safe_math';
|
||||||
export * from '../test/generated-wrappers/lib_safe_math_rich_errors';
|
export * from '../test/generated-wrappers/lib_safe_math_rich_errors';
|
||||||
|
export * from '../test/generated-wrappers/lib_safe_math_rich_errors_v06';
|
||||||
|
export * from '../test/generated-wrappers/lib_safe_math_v06';
|
||||||
export * from '../test/generated-wrappers/ownable';
|
export * from '../test/generated-wrappers/ownable';
|
||||||
|
export * from '../test/generated-wrappers/ownable_v06';
|
||||||
export * from '../test/generated-wrappers/reentrancy_guard';
|
export * from '../test/generated-wrappers/reentrancy_guard';
|
||||||
|
export * from '../test/generated-wrappers/reentrancy_guard_v06';
|
||||||
export * from '../test/generated-wrappers/refundable';
|
export * from '../test/generated-wrappers/refundable';
|
||||||
export * from '../test/generated-wrappers/test_authorizable';
|
export * from '../test/generated-wrappers/test_authorizable';
|
||||||
export * from '../test/generated-wrappers/test_lib_address';
|
export * from '../test/generated-wrappers/test_lib_address';
|
||||||
|
@ -24,15 +24,18 @@
|
|||||||
"generated-artifacts/ReentrancyGuard.json",
|
"generated-artifacts/ReentrancyGuard.json",
|
||||||
"generated-artifacts/Refundable.json",
|
"generated-artifacts/Refundable.json",
|
||||||
"test/generated-artifacts/Authorizable.json",
|
"test/generated-artifacts/Authorizable.json",
|
||||||
|
"test/generated-artifacts/AuthorizableV06.json",
|
||||||
"test/generated-artifacts/D18.json",
|
"test/generated-artifacts/D18.json",
|
||||||
"test/generated-artifacts/DeploymentConstants.json",
|
"test/generated-artifacts/DeploymentConstants.json",
|
||||||
"test/generated-artifacts/IAuthorizable.json",
|
"test/generated-artifacts/IAuthorizable.json",
|
||||||
|
"test/generated-artifacts/IAuthorizableV06.json",
|
||||||
"test/generated-artifacts/IOwnable.json",
|
"test/generated-artifacts/IOwnable.json",
|
||||||
"test/generated-artifacts/IOwnableV06.json",
|
"test/generated-artifacts/IOwnableV06.json",
|
||||||
"test/generated-artifacts/LibAddress.json",
|
"test/generated-artifacts/LibAddress.json",
|
||||||
"test/generated-artifacts/LibAddressArray.json",
|
"test/generated-artifacts/LibAddressArray.json",
|
||||||
"test/generated-artifacts/LibAddressArrayRichErrors.json",
|
"test/generated-artifacts/LibAddressArrayRichErrors.json",
|
||||||
"test/generated-artifacts/LibAuthorizableRichErrors.json",
|
"test/generated-artifacts/LibAuthorizableRichErrors.json",
|
||||||
|
"test/generated-artifacts/LibAuthorizableRichErrorsV06.json",
|
||||||
"test/generated-artifacts/LibBytes.json",
|
"test/generated-artifacts/LibBytes.json",
|
||||||
"test/generated-artifacts/LibBytesRichErrors.json",
|
"test/generated-artifacts/LibBytesRichErrors.json",
|
||||||
"test/generated-artifacts/LibBytesRichErrorsV06.json",
|
"test/generated-artifacts/LibBytesRichErrorsV06.json",
|
||||||
@ -40,14 +43,22 @@
|
|||||||
"test/generated-artifacts/LibEIP1271.json",
|
"test/generated-artifacts/LibEIP1271.json",
|
||||||
"test/generated-artifacts/LibEIP712.json",
|
"test/generated-artifacts/LibEIP712.json",
|
||||||
"test/generated-artifacts/LibFractions.json",
|
"test/generated-artifacts/LibFractions.json",
|
||||||
|
"test/generated-artifacts/LibMathRichErrorsV06.json",
|
||||||
|
"test/generated-artifacts/LibMathV06.json",
|
||||||
"test/generated-artifacts/LibOwnableRichErrors.json",
|
"test/generated-artifacts/LibOwnableRichErrors.json",
|
||||||
|
"test/generated-artifacts/LibOwnableRichErrorsV06.json",
|
||||||
"test/generated-artifacts/LibReentrancyGuardRichErrors.json",
|
"test/generated-artifacts/LibReentrancyGuardRichErrors.json",
|
||||||
|
"test/generated-artifacts/LibReentrancyGuardRichErrorsV06.json",
|
||||||
"test/generated-artifacts/LibRichErrors.json",
|
"test/generated-artifacts/LibRichErrors.json",
|
||||||
"test/generated-artifacts/LibRichErrorsV06.json",
|
"test/generated-artifacts/LibRichErrorsV06.json",
|
||||||
"test/generated-artifacts/LibSafeMath.json",
|
"test/generated-artifacts/LibSafeMath.json",
|
||||||
"test/generated-artifacts/LibSafeMathRichErrors.json",
|
"test/generated-artifacts/LibSafeMathRichErrors.json",
|
||||||
|
"test/generated-artifacts/LibSafeMathRichErrorsV06.json",
|
||||||
|
"test/generated-artifacts/LibSafeMathV06.json",
|
||||||
"test/generated-artifacts/Ownable.json",
|
"test/generated-artifacts/Ownable.json",
|
||||||
|
"test/generated-artifacts/OwnableV06.json",
|
||||||
"test/generated-artifacts/ReentrancyGuard.json",
|
"test/generated-artifacts/ReentrancyGuard.json",
|
||||||
|
"test/generated-artifacts/ReentrancyGuardV06.json",
|
||||||
"test/generated-artifacts/Refundable.json",
|
"test/generated-artifacts/Refundable.json",
|
||||||
"test/generated-artifacts/TestAuthorizable.json",
|
"test/generated-artifacts/TestAuthorizable.json",
|
||||||
"test/generated-artifacts/TestLibAddress.json",
|
"test/generated-artifacts/TestLibAddress.json",
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Create this package",
|
"note": "Create this package",
|
||||||
"pr": 2540
|
"pr": 2540
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Introduce fill `TransformERC20` feature.",
|
||||||
|
"pr": 2545
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -33,4 +33,14 @@ library LibCommonRichErrors {
|
|||||||
sender
|
sender
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function IllegalReentrancyError()
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("IllegalReentrancyError()"))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibSpenderRichErrors {
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
|
||||||
|
function SpenderERC20TransferFromFailedError(
|
||||||
|
address token,
|
||||||
|
address owner,
|
||||||
|
address to,
|
||||||
|
uint256 amount,
|
||||||
|
bytes memory errorData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("SpenderERC20TransferFromFailedError(address,address,address,uint256,bytes)")),
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
to,
|
||||||
|
amount,
|
||||||
|
errorData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibTransformERC20RichErrors {
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase,separate-by-one-line-in-contract
|
||||||
|
|
||||||
|
function InsufficientEthAttachedError(
|
||||||
|
uint256 ethAttached,
|
||||||
|
uint256 ethNeeded
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("InsufficientEthAttachedError(uint256,uint256)")),
|
||||||
|
ethAttached,
|
||||||
|
ethNeeded
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IncompleteTransformERC20Error(
|
||||||
|
address outputToken,
|
||||||
|
uint256 outputTokenAmount,
|
||||||
|
uint256 minOutputTokenAmount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("IncompleteTransformERC20Error(address,uint256,uint256)")),
|
||||||
|
outputToken,
|
||||||
|
outputTokenAmount,
|
||||||
|
minOutputTokenAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function NegativeTransformERC20OutputError(
|
||||||
|
address outputToken,
|
||||||
|
uint256 outputTokenLostAmount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("NegativeTransformERC20OutputError(address,uint256)")),
|
||||||
|
outputToken,
|
||||||
|
outputTokenLostAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function UnauthorizedTransformerError(
|
||||||
|
address transformer,
|
||||||
|
bytes memory rlpNonce
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("UnauthorizedTransformerError(address,bytes)")),
|
||||||
|
transformer,
|
||||||
|
rlpNonce
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InvalidRLPNonceError(
|
||||||
|
bytes memory rlpNonce
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("InvalidRLPNonceError(bytes)")),
|
||||||
|
rlpNonce
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FillQuoteTransformer errors /////////////////////////////////////////////
|
||||||
|
|
||||||
|
function IncompleteFillSellQuoteError(
|
||||||
|
address sellToken,
|
||||||
|
uint256 soldAmount,
|
||||||
|
uint256 sellAmount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("IncompleteFillSellQuoteError(address,uint256,uint256)")),
|
||||||
|
sellToken,
|
||||||
|
soldAmount,
|
||||||
|
sellAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function IncompleteFillBuyQuoteError(
|
||||||
|
address buyToken,
|
||||||
|
uint256 boughtAmount,
|
||||||
|
uint256 buyAmount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("IncompleteFillBuyQuoteError(address,uint256,uint256)")),
|
||||||
|
buyToken,
|
||||||
|
boughtAmount,
|
||||||
|
buyAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InsufficientTakerTokenError(
|
||||||
|
uint256 tokenBalance,
|
||||||
|
uint256 tokensNeeded
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("InsufficientTakerTokenError(uint256,uint256)")),
|
||||||
|
tokenBalance,
|
||||||
|
tokensNeeded
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InsufficientProtocolFeeError(
|
||||||
|
uint256 ethBalance,
|
||||||
|
uint256 ethNeeded
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("InsufficientProtocolFeeError(uint256,uint256)")),
|
||||||
|
ethBalance,
|
||||||
|
ethNeeded
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InvalidERC20AssetDataError(
|
||||||
|
bytes memory assetData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("InvalidERC20AssetDataError(bytes)")),
|
||||||
|
assetData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WethTransformer errors ////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function WrongNumberOfTokensReceivedError(
|
||||||
|
uint256 actual,
|
||||||
|
uint256 expected
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("WrongNumberOfTokensReceivedError(uint256,uint256)")),
|
||||||
|
actual,
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InvalidTokenReceivedError(
|
||||||
|
address token
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("InvalidTokenReceivedError(address)")),
|
||||||
|
token
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
|
||||||
|
|
||||||
|
library LibWalletRichErrors {
|
||||||
|
|
||||||
|
// solhint-disable func-name-mixedcase
|
||||||
|
|
||||||
|
function WalletExecuteCallFailedError(
|
||||||
|
address wallet,
|
||||||
|
address callTarget,
|
||||||
|
bytes memory callData,
|
||||||
|
uint256 callValue,
|
||||||
|
bytes memory errorData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("WalletExecuteCallFailedError(address,address,bytes,uint256,bytes)")),
|
||||||
|
wallet,
|
||||||
|
callTarget,
|
||||||
|
callData,
|
||||||
|
callValue,
|
||||||
|
errorData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function WalletExecuteDelegateCallFailedError(
|
||||||
|
address wallet,
|
||||||
|
address callTarget,
|
||||||
|
bytes memory callData,
|
||||||
|
bytes memory errorData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes memory)
|
||||||
|
{
|
||||||
|
return abi.encodeWithSelector(
|
||||||
|
bytes4(keccak256("WalletExecuteDelegateCallFailedError(address,address,bytes,bytes)")),
|
||||||
|
wallet,
|
||||||
|
callTarget,
|
||||||
|
callData,
|
||||||
|
errorData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
56
contracts/zero-ex/contracts/src/external/AllowanceTarget.sol
vendored
Normal file
56
contracts/zero-ex/contracts/src/external/AllowanceTarget.sol
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/AuthorizableV06.sol";
|
||||||
|
import "../errors/LibSpenderRichErrors.sol";
|
||||||
|
import "./IAllowanceTarget.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev The allowance target for the TokenSpender feature.
|
||||||
|
contract AllowanceTarget is
|
||||||
|
IAllowanceTarget,
|
||||||
|
AuthorizableV06
|
||||||
|
{
|
||||||
|
// solhint-disable no-unused-vars,indent,no-empty-blocks
|
||||||
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
|
/// @dev Execute an arbitrary call. Only an authority can call this.
|
||||||
|
/// @param target The call target.
|
||||||
|
/// @param callData The call data.
|
||||||
|
/// @return resultData The data returned by the call.
|
||||||
|
function executeCall(
|
||||||
|
address payable target,
|
||||||
|
bytes calldata callData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
override
|
||||||
|
onlyAuthorized
|
||||||
|
returns (bytes memory resultData)
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
(success, resultData) = target.call(callData);
|
||||||
|
if (!success) {
|
||||||
|
resultData.rrevert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
175
contracts/zero-ex/contracts/src/external/FlashWallet.sol
vendored
Normal file
175
contracts/zero-ex/contracts/src/external/FlashWallet.sol
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibOwnableRichErrorsV06.sol";
|
||||||
|
import "../errors/LibWalletRichErrors.sol";
|
||||||
|
import "./IFlashWallet.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev A contract that can execute arbitrary calls from its owner.
|
||||||
|
contract FlashWallet is
|
||||||
|
IFlashWallet
|
||||||
|
{
|
||||||
|
// solhint-disable no-unused-vars,indent,no-empty-blocks
|
||||||
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
|
// solhint-disable
|
||||||
|
/// @dev Store the owner/deployer as an immutable to make this contract stateless.
|
||||||
|
address public override immutable owner;
|
||||||
|
// solhint-enable
|
||||||
|
|
||||||
|
constructor() public {
|
||||||
|
// The deployer is the owner.
|
||||||
|
owner = msg.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Allows only the (immutable) owner to call a function.
|
||||||
|
modifier onlyOwner() virtual {
|
||||||
|
if (msg.sender != owner) {
|
||||||
|
LibOwnableRichErrorsV06.OnlyOwnerError(
|
||||||
|
msg.sender,
|
||||||
|
owner
|
||||||
|
).rrevert();
|
||||||
|
}
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Execute an arbitrary call. Only an authority can call this.
|
||||||
|
/// @param target The call target.
|
||||||
|
/// @param callData The call data.
|
||||||
|
/// @param value Ether to attach to the call.
|
||||||
|
/// @return resultData The data returned by the call.
|
||||||
|
function executeCall(
|
||||||
|
address payable target,
|
||||||
|
bytes calldata callData,
|
||||||
|
uint256 value
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
override
|
||||||
|
onlyOwner
|
||||||
|
returns (bytes memory resultData)
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
(success, resultData) = target.call{value: value}(callData);
|
||||||
|
if (!success) {
|
||||||
|
LibWalletRichErrors
|
||||||
|
.WalletExecuteCallFailedError(
|
||||||
|
address(this),
|
||||||
|
target,
|
||||||
|
callData,
|
||||||
|
value,
|
||||||
|
resultData
|
||||||
|
)
|
||||||
|
.rrevert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Execute an arbitrary delegatecall, in the context of this puppet.
|
||||||
|
/// Only an authority can call this.
|
||||||
|
/// @param target The call target.
|
||||||
|
/// @param callData The call data.
|
||||||
|
/// @return resultData The data returned by the call.
|
||||||
|
function executeDelegateCall(
|
||||||
|
address payable target,
|
||||||
|
bytes calldata callData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
override
|
||||||
|
onlyOwner
|
||||||
|
returns (bytes memory resultData)
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
(success, resultData) = target.delegatecall(callData);
|
||||||
|
if (!success) {
|
||||||
|
LibWalletRichErrors
|
||||||
|
.WalletExecuteDelegateCallFailedError(
|
||||||
|
address(this),
|
||||||
|
target,
|
||||||
|
callData,
|
||||||
|
resultData
|
||||||
|
)
|
||||||
|
.rrevert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// solhint-disable
|
||||||
|
/// @dev Allows this contract to receive ether.
|
||||||
|
receive() external override payable {}
|
||||||
|
// solhint-enable
|
||||||
|
|
||||||
|
/// @dev Signal support for receiving ERC1155 tokens.
|
||||||
|
/// @param interfaceID The interface ID, as per ERC-165 rules.
|
||||||
|
/// @return hasSupport `true` if this contract supports an ERC-165 interface.
|
||||||
|
function supportsInterface(bytes4 interfaceID)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bool hasSupport)
|
||||||
|
{
|
||||||
|
return interfaceID == this.supportsInterface.selector ||
|
||||||
|
interfaceID == this.onERC1155Received.selector ^ this.onERC1155BatchReceived.selector ||
|
||||||
|
interfaceID == this.tokenFallback.selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Allow this contract to receive ERC1155 tokens.
|
||||||
|
/// @return success `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
|
||||||
|
function onERC1155Received(
|
||||||
|
address, // operator,
|
||||||
|
address, // from,
|
||||||
|
uint256, // id,
|
||||||
|
uint256, // value,
|
||||||
|
bytes calldata //data
|
||||||
|
)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bytes4 success)
|
||||||
|
{
|
||||||
|
return this.onERC1155Received.selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Allow this contract to receive ERC1155 tokens.
|
||||||
|
/// @return success `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
|
||||||
|
function onERC1155BatchReceived(
|
||||||
|
address, // operator,
|
||||||
|
address, // from,
|
||||||
|
uint256[] calldata, // ids,
|
||||||
|
uint256[] calldata, // values,
|
||||||
|
bytes calldata // data
|
||||||
|
)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bytes4 success)
|
||||||
|
{
|
||||||
|
return this.onERC1155BatchReceived.selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Allows this contract to receive ERC223 tokens.
|
||||||
|
function tokenFallback(
|
||||||
|
address, // from,
|
||||||
|
uint256, // value,
|
||||||
|
bytes calldata // value
|
||||||
|
)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
{}
|
||||||
|
}
|
40
contracts/zero-ex/contracts/src/external/IAllowanceTarget.sol
vendored
Normal file
40
contracts/zero-ex/contracts/src/external/IAllowanceTarget.sol
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/interfaces/IAuthorizableV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev The allowance target for the TokenSpender feature.
|
||||||
|
interface IAllowanceTarget is
|
||||||
|
IAuthorizableV06
|
||||||
|
{
|
||||||
|
/// @dev Execute an arbitrary call. Only an authority can call this.
|
||||||
|
/// @param target The call target.
|
||||||
|
/// @param callData The call data.
|
||||||
|
/// @return resultData The data returned by the call.
|
||||||
|
function executeCall(
|
||||||
|
address payable target,
|
||||||
|
bytes calldata callData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (bytes memory resultData);
|
||||||
|
}
|
61
contracts/zero-ex/contracts/src/external/IFlashWallet.sol
vendored
Normal file
61
contracts/zero-ex/contracts/src/external/IFlashWallet.sol
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/interfaces/IOwnableV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev A contract that can execute arbitrary calls from its owner.
|
||||||
|
interface IFlashWallet {
|
||||||
|
|
||||||
|
/// @dev Execute an arbitrary call. Only an authority can call this.
|
||||||
|
/// @param target The call target.
|
||||||
|
/// @param callData The call data.
|
||||||
|
/// @param value Ether to attach to the call.
|
||||||
|
/// @return resultData The data returned by the call.
|
||||||
|
function executeCall(
|
||||||
|
address payable target,
|
||||||
|
bytes calldata callData,
|
||||||
|
uint256 value
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (bytes memory resultData);
|
||||||
|
|
||||||
|
/// @dev Execute an arbitrary delegatecall, in the context of this puppet.
|
||||||
|
/// Only an authority can call this.
|
||||||
|
/// @param target The call target.
|
||||||
|
/// @param callData The call data.
|
||||||
|
/// @return resultData The data returned by the call.
|
||||||
|
function executeDelegateCall(
|
||||||
|
address payable target,
|
||||||
|
bytes calldata callData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (bytes memory resultData);
|
||||||
|
|
||||||
|
/// @dev Allows the puppet to receive ETH.
|
||||||
|
receive() external payable;
|
||||||
|
|
||||||
|
/// @dev Fetch the immutable owner/deployer of this contract.
|
||||||
|
/// @return owner_ The immutable owner/deployer/
|
||||||
|
function owner() external view returns (address owner_);
|
||||||
|
}
|
55
contracts/zero-ex/contracts/src/features/ITokenSpender.sol
Normal file
55
contracts/zero-ex/contracts/src/features/ITokenSpender.sol
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Feature that allows spending token allowances.
|
||||||
|
interface ITokenSpender {
|
||||||
|
|
||||||
|
/// @dev Transfers ERC20 tokens from `owner` to `to`.
|
||||||
|
/// Only callable from within.
|
||||||
|
/// @param token The token to spend.
|
||||||
|
/// @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;
|
||||||
|
|
||||||
|
/// @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);
|
||||||
|
|
||||||
|
/// @dev Get the address of the allowance target.
|
||||||
|
/// @return target The target of token allowances.
|
||||||
|
function getAllowanceTarget() external view returns (address target);
|
||||||
|
}
|
126
contracts/zero-ex/contracts/src/features/ITransformERC20.sol
Normal file
126
contracts/zero-ex/contracts/src/features/ITransformERC20.sol
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
import "../transformers/IERC20Transformer.sol";
|
||||||
|
import "../external/IFlashWallet.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Feature to composably transform between ERC20 tokens.
|
||||||
|
interface ITransformERC20 {
|
||||||
|
|
||||||
|
/// @dev Defines a transformation to run in `transformERC20()`.
|
||||||
|
struct Transformation {
|
||||||
|
// The transformation handler.
|
||||||
|
// Can receive the entire balance of `tokens`.
|
||||||
|
IERC20Transformer transformer;
|
||||||
|
// Arbitrary data to pass to the transformer.
|
||||||
|
bytes data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Raised upon a successful `transformERC20`.
|
||||||
|
/// @param taker The taker (caller) address.
|
||||||
|
/// @param inputToken The token being provided by the taker.
|
||||||
|
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||||
|
/// @param outputToken The token to be acquired by the taker.
|
||||||
|
/// `0xeee...` implies ETH.
|
||||||
|
/// @param inputTokenAmount The amount of `inputToken` to take from the taker.
|
||||||
|
/// @param outputTokenAmount The amount of `outputToken` received by the taker.
|
||||||
|
event TransformedERC20(
|
||||||
|
address indexed taker,
|
||||||
|
address inputToken,
|
||||||
|
address outputToken,
|
||||||
|
uint256 inputTokenAmount,
|
||||||
|
uint256 outputTokenAmount
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @dev Deploy a new flash wallet instance and replace the current one with it.
|
||||||
|
/// Useful if we somehow break the current wallet instance.
|
||||||
|
/// Anyone can call this.
|
||||||
|
/// @return wallet The new wallet instance.
|
||||||
|
function createTransformWallet()
|
||||||
|
external
|
||||||
|
returns (IFlashWallet wallet);
|
||||||
|
|
||||||
|
/// @dev Executes a series of transformations to convert an ERC20 `inputToken`
|
||||||
|
/// to an ERC20 `outputToken`.
|
||||||
|
/// @param inputToken The token being provided by the sender.
|
||||||
|
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||||
|
/// @param outputToken The token to be acquired by the sender.
|
||||||
|
/// `0xeee...` implies ETH.
|
||||||
|
/// @param inputTokenAmount The amount of `inputToken` to take from the sender.
|
||||||
|
/// @param minOutputTokenAmount The minimum amount of `outputToken` the sender
|
||||||
|
/// must receive for the entire transformation to succeed.
|
||||||
|
/// @param transformations The transformations to execute on the token balance(s)
|
||||||
|
/// in sequence.
|
||||||
|
/// @return outputTokenAmount The amount of `outputToken` received by the sender.
|
||||||
|
function transformERC20(
|
||||||
|
IERC20TokenV06 inputToken,
|
||||||
|
IERC20TokenV06 outputToken,
|
||||||
|
uint256 inputTokenAmount,
|
||||||
|
uint256 minOutputTokenAmount,
|
||||||
|
Transformation[] calldata transformations
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 outputTokenAmount);
|
||||||
|
|
||||||
|
/// @dev Internal version of `transformERC20()`. Only callable from within.
|
||||||
|
/// @param callDataHash Hash of the ingress calldata.
|
||||||
|
/// @param taker The taker address.
|
||||||
|
/// @param inputToken The token being provided by the taker.
|
||||||
|
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||||
|
/// @param outputToken The token to be acquired by the taker.
|
||||||
|
/// `0xeee...` implies ETH.
|
||||||
|
/// @param inputTokenAmount The amount of `inputToken` to take from the taker.
|
||||||
|
/// @param minOutputTokenAmount The minimum amount of `outputToken` the taker
|
||||||
|
/// must receive for the entire transformation to succeed.
|
||||||
|
/// @param transformations The transformations to execute on the token balance(s)
|
||||||
|
/// in sequence.
|
||||||
|
/// @return outputTokenAmount The amount of `outputToken` received by the taker.
|
||||||
|
function _transformERC20(
|
||||||
|
bytes32 callDataHash,
|
||||||
|
address payable taker,
|
||||||
|
IERC20TokenV06 inputToken,
|
||||||
|
IERC20TokenV06 outputToken,
|
||||||
|
uint256 inputTokenAmount,
|
||||||
|
uint256 minOutputTokenAmount,
|
||||||
|
Transformation[] calldata transformations
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 outputTokenAmount);
|
||||||
|
|
||||||
|
/// @dev Return the current wallet instance that will serve as the execution
|
||||||
|
/// context for transformations.
|
||||||
|
/// @return wallet The wallet instance.
|
||||||
|
function getTransformWallet()
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (IFlashWallet wallet);
|
||||||
|
|
||||||
|
/// @dev Return the allowed deployer for transformers.
|
||||||
|
/// @return deployer The transform deployer address.
|
||||||
|
function getTransformerDeployer()
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (address deployer);
|
||||||
|
}
|
@ -37,14 +37,11 @@ contract Ownable is
|
|||||||
FixinCommon
|
FixinCommon
|
||||||
{
|
{
|
||||||
|
|
||||||
// solhint-disable const-name-snakecase
|
|
||||||
/// @dev Name of this feature.
|
|
||||||
string constant public override FEATURE_NAME = "Ownable";
|
|
||||||
/// @dev Version of this feature.
|
|
||||||
uint256 constant public override FEATURE_VERSION = (1 << 64) | (0 << 32) | (0);
|
|
||||||
// solhint-enable const-name-snakecase
|
|
||||||
|
|
||||||
// solhint-disable
|
// solhint-disable
|
||||||
|
/// @dev Name of this feature.
|
||||||
|
string public constant override FEATURE_NAME = "Ownable";
|
||||||
|
/// @dev Version of this feature.
|
||||||
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
||||||
/// @dev The deployed address of this contract.
|
/// @dev The deployed address of this contract.
|
||||||
address immutable private _implementation;
|
address immutable private _implementation;
|
||||||
// solhint-enable
|
// solhint-enable
|
||||||
|
@ -35,17 +35,13 @@ contract SimpleFunctionRegistry is
|
|||||||
ISimpleFunctionRegistry,
|
ISimpleFunctionRegistry,
|
||||||
FixinCommon
|
FixinCommon
|
||||||
{
|
{
|
||||||
|
|
||||||
// solhint-disable const-name-snakecase
|
|
||||||
/// @dev Name of this feature.
|
|
||||||
string constant public override FEATURE_NAME = "SimpleFunctionRegistry";
|
|
||||||
/// @dev Version of this feature.
|
|
||||||
uint256 constant public override FEATURE_VERSION = (1 << 64) | (0 << 32) | (0);
|
|
||||||
// solhint-enable const-name-snakecase
|
|
||||||
|
|
||||||
// solhint-disable
|
// solhint-disable
|
||||||
|
/// @dev Name of this feature.
|
||||||
|
string public constant override FEATURE_NAME = "SimpleFunctionRegistry";
|
||||||
|
/// @dev Version of this feature.
|
||||||
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
||||||
/// @dev The deployed address of this contract.
|
/// @dev The deployed address of this contract.
|
||||||
address immutable private _implementation;
|
address private immutable _implementation;
|
||||||
// solhint-enable
|
// solhint-enable
|
||||||
|
|
||||||
using LibRichErrorsV06 for bytes;
|
using LibRichErrorsV06 for bytes;
|
||||||
@ -55,16 +51,15 @@ contract SimpleFunctionRegistry is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Initializes this feature.
|
/// @dev Initializes this feature.
|
||||||
/// @param impl The actual address of this feature contract.
|
|
||||||
/// @return success Magic bytes if successful.
|
/// @return success Magic bytes if successful.
|
||||||
function bootstrap(address impl) external returns (bytes4 success) {
|
function bootstrap() external returns (bytes4 success) {
|
||||||
// Register the registration functions (inception vibes).
|
// Register the registration functions (inception vibes).
|
||||||
_extend(this.extend.selector, impl);
|
_extend(this.extend.selector, _implementation);
|
||||||
// Register the rollback function.
|
// Register the rollback function.
|
||||||
_extend(this.rollback.selector, impl);
|
_extend(this.rollback.selector, _implementation);
|
||||||
// Register getters.
|
// Register getters.
|
||||||
_extend(this.getRollbackLength.selector, impl);
|
_extend(this.getRollbackLength.selector, _implementation);
|
||||||
_extend(this.getRollbackEntryAtIndex.selector, impl);
|
_extend(this.getRollbackEntryAtIndex.selector, _implementation);
|
||||||
return LibBootstrap.BOOTSTRAP_SUCCESS;
|
return LibBootstrap.BOOTSTRAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
143
contracts/zero-ex/contracts/src/features/TokenSpender.sol
Normal file
143
contracts/zero-ex/contracts/src/features/TokenSpender.sol
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
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 "../errors/LibSpenderRichErrors.sol";
|
||||||
|
import "../fixins/FixinCommon.sol";
|
||||||
|
import "../migrations/LibMigrate.sol";
|
||||||
|
import "../external/IAllowanceTarget.sol";
|
||||||
|
import "../storage/LibTokenSpenderStorage.sol";
|
||||||
|
import "./ITokenSpender.sol";
|
||||||
|
import "./IFeature.sol";
|
||||||
|
import "./ISimpleFunctionRegistry.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Feature that allows spending token allowances.
|
||||||
|
contract TokenSpender is
|
||||||
|
IFeature,
|
||||||
|
ITokenSpender,
|
||||||
|
FixinCommon
|
||||||
|
{
|
||||||
|
// solhint-disable
|
||||||
|
/// @dev Name of this feature.
|
||||||
|
string public constant override FEATURE_NAME = "TokenSpender";
|
||||||
|
/// @dev Version of this feature.
|
||||||
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
||||||
|
/// @dev The implementation address of this feature.
|
||||||
|
address private immutable _implementation;
|
||||||
|
// solhint-enable
|
||||||
|
|
||||||
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
|
constructor() public {
|
||||||
|
_implementation = address(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Initialize and register this feature. Should be delegatecalled
|
||||||
|
/// into during a `Migrate.migrate()`.
|
||||||
|
/// @param allowanceTarget An `allowanceTarget` instance, configured to have
|
||||||
|
/// the ZeroeEx contract as an authority.
|
||||||
|
/// @return success `MIGRATE_SUCCESS` on success.
|
||||||
|
function migrate(IAllowanceTarget allowanceTarget) external returns (bytes4 success) {
|
||||||
|
LibTokenSpenderStorage.getStorage().allowanceTarget = allowanceTarget;
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this.getAllowanceTarget.selector, _implementation);
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this._spendERC20Tokens.selector, _implementation);
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this.getSpendableERC20BalanceOf.selector, _implementation);
|
||||||
|
return LibMigrate.MIGRATE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Transfers ERC20 tokens from `owner` to `to`. Only callable from within.
|
||||||
|
/// @param token The token to spend.
|
||||||
|
/// @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
|
||||||
|
override
|
||||||
|
onlySelf
|
||||||
|
{
|
||||||
|
IAllowanceTarget spender = LibTokenSpenderStorage.getStorage().allowanceTarget;
|
||||||
|
// Have the allowance target execute an ERC20 `transferFrom()`.
|
||||||
|
(bool didSucceed, bytes memory resultData) = address(spender).call(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IAllowanceTarget.executeCall.selector,
|
||||||
|
address(token),
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IERC20TokenV06.transferFrom.selector,
|
||||||
|
owner,
|
||||||
|
to,
|
||||||
|
amount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (didSucceed) {
|
||||||
|
resultData = abi.decode(resultData, (bytes));
|
||||||
|
}
|
||||||
|
if (!didSucceed || !LibERC20TokenV06.isSuccessfulResult(resultData)) {
|
||||||
|
LibSpenderRichErrors.SpenderERC20TransferFromFailedError(
|
||||||
|
address(token),
|
||||||
|
owner,
|
||||||
|
to,
|
||||||
|
amount,
|
||||||
|
resultData
|
||||||
|
).rrevert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
|
||||||
|
/// pulled from `owner` by the token spender.
|
||||||
|
/// @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
|
||||||
|
override
|
||||||
|
view
|
||||||
|
returns (uint256 amount)
|
||||||
|
{
|
||||||
|
return LibSafeMathV06.min256(
|
||||||
|
token.allowance(owner, address(LibTokenSpenderStorage.getStorage().allowanceTarget)),
|
||||||
|
token.balanceOf(owner)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Get the address of the allowance target.
|
||||||
|
/// @return target The target of token allowances.
|
||||||
|
function getAllowanceTarget()
|
||||||
|
external
|
||||||
|
override
|
||||||
|
view
|
||||||
|
returns (address target)
|
||||||
|
{
|
||||||
|
return address(LibTokenSpenderStorage.getStorage().allowanceTarget);
|
||||||
|
}
|
||||||
|
}
|
376
contracts/zero-ex/contracts/src/features/TransformERC20.sol
Normal file
376
contracts/zero-ex/contracts/src/features/TransformERC20.sol
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||||
|
import "../errors/LibTransformERC20RichErrors.sol";
|
||||||
|
import "../fixins/FixinCommon.sol";
|
||||||
|
import "../migrations/LibMigrate.sol";
|
||||||
|
import "../external/IFlashWallet.sol";
|
||||||
|
import "../external/FlashWallet.sol";
|
||||||
|
import "../storage/LibTransformERC20Storage.sol";
|
||||||
|
import "../transformers/IERC20Transformer.sol";
|
||||||
|
import "../transformers/LibERC20Transformer.sol";
|
||||||
|
import "./ITransformERC20.sol";
|
||||||
|
import "./ITokenSpender.sol";
|
||||||
|
import "./IFeature.sol";
|
||||||
|
import "./ISimpleFunctionRegistry.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Feature to composably transform between ERC20 tokens.
|
||||||
|
contract TransformERC20 is
|
||||||
|
IFeature,
|
||||||
|
ITransformERC20,
|
||||||
|
FixinCommon
|
||||||
|
{
|
||||||
|
|
||||||
|
// solhint-disable
|
||||||
|
/// @dev Name of this feature.
|
||||||
|
string public constant override FEATURE_NAME = "TransformERC20";
|
||||||
|
/// @dev Version of this feature.
|
||||||
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
||||||
|
/// @dev The trusted deployer for all transformers.
|
||||||
|
address public immutable transformDeployer;
|
||||||
|
/// @dev The implementation address of this feature.
|
||||||
|
address private immutable _implementation;
|
||||||
|
// solhint-enable
|
||||||
|
|
||||||
|
using LibSafeMathV06 for uint256;
|
||||||
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
|
constructor(address trustedDeployer_) public {
|
||||||
|
_implementation = address(this);
|
||||||
|
transformDeployer = trustedDeployer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Initialize and register this feature.
|
||||||
|
/// Should be delegatecalled by `Migrate.migrate()`.
|
||||||
|
function migrate() external returns (bytes4 success) {
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this.getTransformerDeployer.selector, _implementation);
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this.createTransformWallet.selector, _implementation);
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this.getTransformWallet.selector, _implementation);
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this.transformERC20.selector, _implementation);
|
||||||
|
ISimpleFunctionRegistry(address(this))
|
||||||
|
.extend(this._transformERC20.selector, _implementation);
|
||||||
|
createTransformWallet();
|
||||||
|
return LibMigrate.MIGRATE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Return the allowed deployer for transformers.
|
||||||
|
/// @return deployer The transform deployer address.
|
||||||
|
function getTransformerDeployer()
|
||||||
|
external
|
||||||
|
override
|
||||||
|
view
|
||||||
|
returns (address deployer)
|
||||||
|
{
|
||||||
|
return transformDeployer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Deploy a new wallet instance and replace the current one with it.
|
||||||
|
/// Useful if we somehow break the current wallet instance.
|
||||||
|
/// Anyone can call this.
|
||||||
|
/// @return wallet The new wallet instance.
|
||||||
|
function createTransformWallet()
|
||||||
|
public
|
||||||
|
override
|
||||||
|
returns (IFlashWallet wallet)
|
||||||
|
{
|
||||||
|
wallet = new FlashWallet();
|
||||||
|
LibTransformERC20Storage.getStorage().wallet = wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Executes a series of transformations to convert an ERC20 `inputToken`
|
||||||
|
/// to an ERC20 `outputToken`.
|
||||||
|
/// @param inputToken The token being provided by the sender.
|
||||||
|
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||||
|
/// @param outputToken The token to be acquired by the sender.
|
||||||
|
/// `0xeee...` implies ETH.
|
||||||
|
/// @param inputTokenAmount The amount of `inputToken` to take from the sender.
|
||||||
|
/// If set to `uint256(-1)`, the entire spendable balance of the taker
|
||||||
|
/// will be solt.
|
||||||
|
/// @param minOutputTokenAmount The minimum amount of `outputToken` the sender
|
||||||
|
/// must receive for the entire transformation to succeed. If set to zero,
|
||||||
|
/// the minimum output token transfer will not be asserted.
|
||||||
|
/// @param transformations The transformations to execute on the token balance(s)
|
||||||
|
/// in sequence.
|
||||||
|
/// @return outputTokenAmount The amount of `outputToken` received by the sender.
|
||||||
|
function transformERC20(
|
||||||
|
IERC20TokenV06 inputToken,
|
||||||
|
IERC20TokenV06 outputToken,
|
||||||
|
uint256 inputTokenAmount,
|
||||||
|
uint256 minOutputTokenAmount,
|
||||||
|
Transformation[] memory transformations
|
||||||
|
)
|
||||||
|
public
|
||||||
|
override
|
||||||
|
payable
|
||||||
|
returns (uint256 outputTokenAmount)
|
||||||
|
{
|
||||||
|
return _transformERC20Private(
|
||||||
|
keccak256(msg.data),
|
||||||
|
msg.sender,
|
||||||
|
inputToken,
|
||||||
|
outputToken,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
transformations
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Internal version of `transformERC20()`. Only callable from within.
|
||||||
|
/// @param callDataHash Hash of the ingress calldata.
|
||||||
|
/// @param taker The taker address.
|
||||||
|
/// @param inputToken The token being provided by the taker.
|
||||||
|
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||||
|
/// @param outputToken The token to be acquired by the taker.
|
||||||
|
/// `0xeee...` implies ETH.
|
||||||
|
/// @param inputTokenAmount The amount of `inputToken` to take from the taker.
|
||||||
|
/// If set to `uint256(-1)`, the entire spendable balance of the taker
|
||||||
|
/// will be solt.
|
||||||
|
/// @param minOutputTokenAmount The minimum amount of `outputToken` the taker
|
||||||
|
/// must receive for the entire transformation to succeed. If set to zero,
|
||||||
|
/// the minimum output token transfer will not be asserted.
|
||||||
|
/// @param transformations The transformations to execute on the token balance(s)
|
||||||
|
/// in sequence.
|
||||||
|
/// @return outputTokenAmount The amount of `outputToken` received by the taker.
|
||||||
|
function _transformERC20(
|
||||||
|
bytes32 callDataHash,
|
||||||
|
address payable taker,
|
||||||
|
IERC20TokenV06 inputToken,
|
||||||
|
IERC20TokenV06 outputToken,
|
||||||
|
uint256 inputTokenAmount,
|
||||||
|
uint256 minOutputTokenAmount,
|
||||||
|
Transformation[] memory transformations
|
||||||
|
)
|
||||||
|
public
|
||||||
|
override
|
||||||
|
payable
|
||||||
|
onlySelf
|
||||||
|
returns (uint256 outputTokenAmount)
|
||||||
|
{
|
||||||
|
return _transformERC20Private(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken,
|
||||||
|
outputToken,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
transformations
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Private version of `transformERC20()`.
|
||||||
|
/// @param callDataHash Hash of the ingress calldata.
|
||||||
|
/// @param taker The taker address.
|
||||||
|
/// @param inputToken The token being provided by the taker.
|
||||||
|
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||||
|
/// @param outputToken The token to be acquired by the taker.
|
||||||
|
/// `0xeee...` implies ETH.
|
||||||
|
/// @param inputTokenAmount The amount of `inputToken` to take from the taker.
|
||||||
|
/// If set to `uint256(-1)`, the entire spendable balance of the taker
|
||||||
|
/// will be solt.
|
||||||
|
/// @param minOutputTokenAmount The minimum amount of `outputToken` the taker
|
||||||
|
/// must receive for the entire transformation to succeed. If set to zero,
|
||||||
|
/// the minimum output token transfer will not be asserted.
|
||||||
|
/// @param transformations The transformations to execute on the token balance(s)
|
||||||
|
/// in sequence.
|
||||||
|
/// @return outputTokenAmount The amount of `outputToken` received by the taker.
|
||||||
|
function _transformERC20Private(
|
||||||
|
bytes32 callDataHash,
|
||||||
|
address payable taker,
|
||||||
|
IERC20TokenV06 inputToken,
|
||||||
|
IERC20TokenV06 outputToken,
|
||||||
|
uint256 inputTokenAmount,
|
||||||
|
uint256 minOutputTokenAmount,
|
||||||
|
Transformation[] memory transformations
|
||||||
|
)
|
||||||
|
public
|
||||||
|
payable
|
||||||
|
returns (uint256 outputTokenAmount)
|
||||||
|
{
|
||||||
|
// If the input token amount is -1, transform the taker's entire
|
||||||
|
// spendable balance.
|
||||||
|
if (inputTokenAmount == uint256(-1)) {
|
||||||
|
inputTokenAmount = ITokenSpender(address(this))
|
||||||
|
.getSpendableERC20BalanceOf(inputToken, taker);
|
||||||
|
}
|
||||||
|
|
||||||
|
IFlashWallet wallet = getTransformWallet();
|
||||||
|
|
||||||
|
// Remember the initial output token balance of the taker.
|
||||||
|
uint256 takerOutputTokenBalanceBefore =
|
||||||
|
LibERC20Transformer.getTokenBalanceOf(outputToken, taker);
|
||||||
|
|
||||||
|
// Pull input tokens from the taker to the wallet and transfer attached ETH.
|
||||||
|
_transferInputTokensAndAttachedEth(inputToken, taker, address(wallet), inputTokenAmount);
|
||||||
|
|
||||||
|
// Perform transformations.
|
||||||
|
for (uint256 i = 0; i < transformations.length; ++i) {
|
||||||
|
_executeTransformation(wallet, transformations[i], taker, callDataHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute how much output token has been transferred to the taker.
|
||||||
|
uint256 takerOutputTokenBalanceAfter =
|
||||||
|
LibERC20Transformer.getTokenBalanceOf(outputToken, taker);
|
||||||
|
if (takerOutputTokenBalanceAfter > takerOutputTokenBalanceBefore) {
|
||||||
|
outputTokenAmount = takerOutputTokenBalanceAfter.safeSub(
|
||||||
|
takerOutputTokenBalanceBefore
|
||||||
|
);
|
||||||
|
} else if (takerOutputTokenBalanceAfter < takerOutputTokenBalanceBefore) {
|
||||||
|
LibTransformERC20RichErrors.NegativeTransformERC20OutputError(
|
||||||
|
address(outputToken),
|
||||||
|
takerOutputTokenBalanceBefore - takerOutputTokenBalanceAfter
|
||||||
|
).rrevert();
|
||||||
|
}
|
||||||
|
// Ensure enough output token has been sent to the taker.
|
||||||
|
if (outputTokenAmount < minOutputTokenAmount) {
|
||||||
|
LibTransformERC20RichErrors.IncompleteTransformERC20Error(
|
||||||
|
address(outputToken),
|
||||||
|
outputTokenAmount,
|
||||||
|
minOutputTokenAmount
|
||||||
|
).rrevert();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit an event.
|
||||||
|
emit TransformedERC20(
|
||||||
|
taker,
|
||||||
|
address(inputToken),
|
||||||
|
address(outputToken),
|
||||||
|
inputTokenAmount,
|
||||||
|
outputTokenAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Return the current wallet instance that will serve as the execution
|
||||||
|
/// context for transformations.
|
||||||
|
/// @return wallet The wallet instance.
|
||||||
|
function getTransformWallet()
|
||||||
|
public
|
||||||
|
override
|
||||||
|
view
|
||||||
|
returns (IFlashWallet wallet)
|
||||||
|
{
|
||||||
|
return LibTransformERC20Storage.getStorage().wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Transfer input tokens from the taker and any attached ETH to `to`
|
||||||
|
/// @param inputToken The token to pull from the taker.
|
||||||
|
/// @param from The from (taker) address.
|
||||||
|
/// @param to The recipient of tokens and ETH.
|
||||||
|
/// @param amount Amount of `inputToken` tokens to transfer.
|
||||||
|
function _transferInputTokensAndAttachedEth(
|
||||||
|
IERC20TokenV06 inputToken,
|
||||||
|
address from,
|
||||||
|
address payable to,
|
||||||
|
uint256 amount
|
||||||
|
)
|
||||||
|
private
|
||||||
|
{
|
||||||
|
// Transfer any attached ETH.
|
||||||
|
if (msg.value != 0) {
|
||||||
|
to.transfer(msg.value);
|
||||||
|
}
|
||||||
|
// Transfer input tokens.
|
||||||
|
if (!LibERC20Transformer.isTokenETH(inputToken)) {
|
||||||
|
// Token is not ETH, so pull ERC20 tokens.
|
||||||
|
ITokenSpender(address(this))._spendERC20Tokens(
|
||||||
|
inputToken,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
amount
|
||||||
|
);
|
||||||
|
} else if (msg.value < amount) {
|
||||||
|
// Token is ETH, so the caller must attach enough ETH to the call.
|
||||||
|
LibTransformERC20RichErrors.InsufficientEthAttachedError(
|
||||||
|
msg.value,
|
||||||
|
amount
|
||||||
|
).rrevert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Executs a transformer in the context of `wallet`.
|
||||||
|
/// @param wallet The wallet instance.
|
||||||
|
/// @param transformation The transformation.
|
||||||
|
/// @param taker The taker address.
|
||||||
|
/// @param callDataHash Hash of the calldata.
|
||||||
|
function _executeTransformation(
|
||||||
|
IFlashWallet wallet,
|
||||||
|
Transformation memory transformation,
|
||||||
|
address payable taker,
|
||||||
|
bytes32 callDataHash
|
||||||
|
)
|
||||||
|
private
|
||||||
|
{
|
||||||
|
// Call `transformer.transform()` as the wallet.
|
||||||
|
bytes memory resultData = wallet.executeDelegateCall(
|
||||||
|
// Call target.
|
||||||
|
address(uint160(address(transformation.transformer))),
|
||||||
|
// Call data.
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IERC20Transformer.transform.selector,
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
transformation.data
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// Ensure the transformer returned its valid rlp-encoded deployment nonce.
|
||||||
|
bytes memory rlpNonce = resultData.length == 0
|
||||||
|
? new bytes(0)
|
||||||
|
: abi.decode(resultData, (bytes));
|
||||||
|
if (_getExpectedDeployment(rlpNonce) != address(transformation.transformer)) {
|
||||||
|
LibTransformERC20RichErrors.UnauthorizedTransformerError(
|
||||||
|
address(transformation.transformer),
|
||||||
|
rlpNonce
|
||||||
|
).rrevert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Compute the expected deployment address by `transformDeployer` at
|
||||||
|
/// the nonce given by `rlpNonce`.
|
||||||
|
/// @param rlpNonce The RLP-encoded nonce that
|
||||||
|
/// the deployer had when deploying a contract.
|
||||||
|
/// @return deploymentAddress The deployment address.
|
||||||
|
function _getExpectedDeployment(bytes memory rlpNonce)
|
||||||
|
private
|
||||||
|
view
|
||||||
|
returns (address deploymentAddress)
|
||||||
|
{
|
||||||
|
// See https://github.com/ethereum/wiki/wiki/RLP for RLP encoding rules.
|
||||||
|
// The RLP-encoded nonce may be prefixed with a length byte.
|
||||||
|
// We only support nonces up to 32-bits.
|
||||||
|
if (rlpNonce.length == 0 || rlpNonce.length > 5) {
|
||||||
|
LibTransformERC20RichErrors.InvalidRLPNonceError(rlpNonce).rrevert();
|
||||||
|
}
|
||||||
|
return address(uint160(uint256(keccak256(abi.encodePacked(
|
||||||
|
byte(uint8(0xC0 + 21 + rlpNonce.length)),
|
||||||
|
byte(uint8(0x80 + 20)),
|
||||||
|
transformDeployer,
|
||||||
|
rlpNonce
|
||||||
|
)))));
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
|
|||||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
import "../errors/LibCommonRichErrors.sol";
|
import "../errors/LibCommonRichErrors.sol";
|
||||||
import "../errors/LibOwnableRichErrors.sol";
|
import "../errors/LibOwnableRichErrors.sol";
|
||||||
|
import "../features/IOwnable.sol";
|
||||||
import "../storage/LibOwnableStorage.sol";
|
import "../storage/LibOwnableStorage.sol";
|
||||||
|
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ contract FixinCommon {
|
|||||||
using LibRichErrorsV06 for bytes;
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
/// @dev The caller must be this contract.
|
/// @dev The caller must be this contract.
|
||||||
modifier onlySelf() {
|
modifier onlySelf() virtual {
|
||||||
if (msg.sender != address(this)) {
|
if (msg.sender != address(this)) {
|
||||||
LibCommonRichErrors.OnlyCallableBySelfError(msg.sender).rrevert();
|
LibCommonRichErrors.OnlyCallableBySelfError(msg.sender).rrevert();
|
||||||
}
|
}
|
||||||
@ -39,7 +40,7 @@ contract FixinCommon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev The caller of this function must be the owner.
|
/// @dev The caller of this function must be the owner.
|
||||||
modifier onlyOwner() {
|
modifier onlyOwner() virtual {
|
||||||
{
|
{
|
||||||
address owner = _getOwner();
|
address owner = _getOwner();
|
||||||
if (msg.sender != owner) {
|
if (msg.sender != owner) {
|
||||||
@ -54,7 +55,22 @@ contract FixinCommon {
|
|||||||
|
|
||||||
/// @dev Get the owner of this contract.
|
/// @dev Get the owner of this contract.
|
||||||
/// @return owner The owner of this contract.
|
/// @return owner The owner of this contract.
|
||||||
function _getOwner() internal view returns (address owner) {
|
function _getOwner() internal virtual view returns (address owner) {
|
||||||
|
// We access Ownable's storage directly here instead of using the external
|
||||||
|
// API because `onlyOwner` needs to function during bootstrapping.
|
||||||
return LibOwnableStorage.getStorage().owner;
|
return LibOwnableStorage.getStorage().owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Encode a feature version as a `uint256`.
|
||||||
|
/// @param major The major version number of the feature.
|
||||||
|
/// @param minor The minor version number of the feature.
|
||||||
|
/// @param revision The revision number of the feature.
|
||||||
|
/// @return encodedVersion The encoded version number.
|
||||||
|
function _encodeVersion(uint32 major, uint32 minor, uint32 revision)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256 encodedVersion)
|
||||||
|
{
|
||||||
|
return (major << 64) | (minor << 32) | revision;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
147
contracts/zero-ex/contracts/src/migrations/FullMigration.sol
Normal file
147
contracts/zero-ex/contracts/src/migrations/FullMigration.sol
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "../ZeroEx.sol";
|
||||||
|
import "../features/IOwnable.sol";
|
||||||
|
import "../features/TokenSpender.sol";
|
||||||
|
import "../features/TransformERC20.sol";
|
||||||
|
import "../external/AllowanceTarget.sol";
|
||||||
|
import "./InitialMigration.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev A contract for deploying and configuring the full ZeroEx contract.
|
||||||
|
contract FullMigration {
|
||||||
|
|
||||||
|
// solhint-disable no-empty-blocks,indent
|
||||||
|
|
||||||
|
/// @dev Features to add the the proxy contract.
|
||||||
|
struct Features {
|
||||||
|
SimpleFunctionRegistry registry;
|
||||||
|
Ownable ownable;
|
||||||
|
TokenSpender tokenSpender;
|
||||||
|
TransformERC20 transformERC20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev The allowed caller of `deploy()`.
|
||||||
|
address public immutable deployer;
|
||||||
|
/// @dev The initial migration contract.
|
||||||
|
InitialMigration private _initialMigration;
|
||||||
|
|
||||||
|
/// @dev Instantiate this contract and set the allowed caller of `deploy()`
|
||||||
|
/// to `deployer`.
|
||||||
|
/// @param deployer_ The allowed caller of `deploy()`.
|
||||||
|
constructor(address payable deployer_)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
deployer = deployer_;
|
||||||
|
// Create an initial migration contract with this contract set to the
|
||||||
|
// allowed deployer.
|
||||||
|
_initialMigration = new InitialMigration(address(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Deploy the `ZeroEx` contract with the full feature set,
|
||||||
|
/// transfer ownership to `owner`, then self-destruct.
|
||||||
|
/// @param owner The owner of the contract.
|
||||||
|
/// @param features Features to add to the proxy.
|
||||||
|
/// @return zeroEx The deployed and configured `ZeroEx` contract.
|
||||||
|
function deploy(
|
||||||
|
address payable owner,
|
||||||
|
Features memory features
|
||||||
|
)
|
||||||
|
public
|
||||||
|
returns (ZeroEx zeroEx)
|
||||||
|
{
|
||||||
|
require(msg.sender == deployer, "FullMigration/INVALID_SENDER");
|
||||||
|
|
||||||
|
// Perform the initial migration with the owner set to this contract.
|
||||||
|
zeroEx = _initialMigration.deploy(
|
||||||
|
address(uint160(address(this))),
|
||||||
|
InitialMigration.BootstrapFeatures({
|
||||||
|
registry: features.registry,
|
||||||
|
ownable: features.ownable
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add features.
|
||||||
|
_addFeatures(zeroEx, owner, features);
|
||||||
|
|
||||||
|
// Transfer ownership to the real owner.
|
||||||
|
IOwnable(address(zeroEx)).transferOwnership(owner);
|
||||||
|
|
||||||
|
// Self-destruct.
|
||||||
|
this.die(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Destroy this contract. Only callable from ourselves (from `deploy()`).
|
||||||
|
/// @param ethRecipient Receiver of any ETH in this contract.
|
||||||
|
function die(address payable ethRecipient)
|
||||||
|
external
|
||||||
|
virtual
|
||||||
|
{
|
||||||
|
require(msg.sender == address(this), "FullMigration/INVALID_SENDER");
|
||||||
|
// This contract should not hold any funds but we send
|
||||||
|
// them to the ethRecipient just in case.
|
||||||
|
selfdestruct(ethRecipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Deploy and register features to the ZeroEx contract.
|
||||||
|
/// @param zeroEx The bootstrapped ZeroEx contract.
|
||||||
|
/// @param owner The ultimate owner of the ZeroEx contract.
|
||||||
|
/// @param features Features to add to the proxy.
|
||||||
|
function _addFeatures(
|
||||||
|
ZeroEx zeroEx,
|
||||||
|
address owner,
|
||||||
|
Features memory features
|
||||||
|
)
|
||||||
|
private
|
||||||
|
{
|
||||||
|
IOwnable ownable = IOwnable(address(zeroEx));
|
||||||
|
// TokenSpender
|
||||||
|
{
|
||||||
|
// Create the allowance target.
|
||||||
|
AllowanceTarget allowanceTarget = new AllowanceTarget();
|
||||||
|
// Let the ZeroEx contract use the allowance target.
|
||||||
|
allowanceTarget.addAuthorizedAddress(address(zeroEx));
|
||||||
|
// Transfer ownership of the allowance target to the (real) owner.
|
||||||
|
allowanceTarget.transferOwnership(owner);
|
||||||
|
// Register the feature.
|
||||||
|
ownable.migrate(
|
||||||
|
address(features.tokenSpender),
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
TokenSpender.migrate.selector,
|
||||||
|
allowanceTarget
|
||||||
|
),
|
||||||
|
address(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// TransformERC20
|
||||||
|
{
|
||||||
|
// Register the feature.
|
||||||
|
ownable.migrate(
|
||||||
|
address(features.transformERC20),
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
TransformERC20.migrate.selector
|
||||||
|
),
|
||||||
|
address(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,12 @@ import "./LibBootstrap.sol";
|
|||||||
/// @dev A contract for deploying and configuring a minimal ZeroEx contract.
|
/// @dev A contract for deploying and configuring a minimal ZeroEx contract.
|
||||||
contract InitialMigration {
|
contract InitialMigration {
|
||||||
|
|
||||||
|
/// @dev Features to bootstrap into the the proxy contract.
|
||||||
|
struct BootstrapFeatures {
|
||||||
|
SimpleFunctionRegistry registry;
|
||||||
|
Ownable ownable;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev The allowed caller of `deploy()`. In production, this would be
|
/// @dev The allowed caller of `deploy()`. In production, this would be
|
||||||
/// the governor.
|
/// the governor.
|
||||||
address public immutable deployer;
|
address public immutable deployer;
|
||||||
@ -47,8 +53,13 @@ contract InitialMigration {
|
|||||||
/// transfers ownership to `owner`, then self-destructs.
|
/// transfers ownership to `owner`, then self-destructs.
|
||||||
/// Only callable by `deployer` set in the contstructor.
|
/// Only callable by `deployer` set in the contstructor.
|
||||||
/// @param owner The owner of the contract.
|
/// @param owner The owner of the contract.
|
||||||
|
/// @param features Features to bootstrap into the proxy.
|
||||||
/// @return zeroEx The deployed and configured `ZeroEx` contract.
|
/// @return zeroEx The deployed and configured `ZeroEx` contract.
|
||||||
function deploy(address payable owner) public virtual returns (ZeroEx zeroEx) {
|
function deploy(address payable owner, BootstrapFeatures memory features)
|
||||||
|
public
|
||||||
|
virtual
|
||||||
|
returns (ZeroEx zeroEx)
|
||||||
|
{
|
||||||
// Must be called by the allowed deployer.
|
// Must be called by the allowed deployer.
|
||||||
require(msg.sender == deployer, "InitialMigration/INVALID_SENDER");
|
require(msg.sender == deployer, "InitialMigration/INVALID_SENDER");
|
||||||
|
|
||||||
@ -58,7 +69,7 @@ contract InitialMigration {
|
|||||||
// Bootstrap the initial feature set.
|
// Bootstrap the initial feature set.
|
||||||
IBootstrap(address(zeroEx)).bootstrap(
|
IBootstrap(address(zeroEx)).bootstrap(
|
||||||
address(this),
|
address(this),
|
||||||
abi.encodeWithSelector(this.bootstrap.selector, owner)
|
abi.encodeWithSelector(this.bootstrap.selector, owner, features)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Self-destruct. This contract should not hold any funds but we send
|
// Self-destruct. This contract should not hold any funds but we send
|
||||||
@ -69,23 +80,30 @@ contract InitialMigration {
|
|||||||
/// @dev Sets up the initial state of the `ZeroEx` contract.
|
/// @dev Sets up the initial state of the `ZeroEx` contract.
|
||||||
/// The `ZeroEx` contract will delegatecall into this function.
|
/// The `ZeroEx` contract will delegatecall into this function.
|
||||||
/// @param owner The new owner of the ZeroEx contract.
|
/// @param owner The new owner of the ZeroEx contract.
|
||||||
|
/// @param features Features to bootstrap into the proxy.
|
||||||
/// @return success Magic bytes if successful.
|
/// @return success Magic bytes if successful.
|
||||||
function bootstrap(address owner) public virtual returns (bytes4 success) {
|
function bootstrap(address owner, BootstrapFeatures memory features)
|
||||||
|
public
|
||||||
|
virtual
|
||||||
|
returns (bytes4 success)
|
||||||
|
{
|
||||||
// Deploy and migrate the initial features.
|
// Deploy and migrate the initial features.
|
||||||
// Order matters here.
|
// Order matters here.
|
||||||
|
|
||||||
// Initialize Registry.
|
// Initialize Registry.
|
||||||
SimpleFunctionRegistry registry = new SimpleFunctionRegistry();
|
|
||||||
LibBootstrap.delegatecallBootstrapFunction(
|
LibBootstrap.delegatecallBootstrapFunction(
|
||||||
address(registry),
|
address(features.registry),
|
||||||
abi.encodeWithSelector(registry.bootstrap.selector, address(registry))
|
abi.encodeWithSelector(
|
||||||
|
SimpleFunctionRegistry.bootstrap.selector
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize Ownable.
|
// Initialize Ownable.
|
||||||
Ownable ownable = new Ownable();
|
|
||||||
LibBootstrap.delegatecallBootstrapFunction(
|
LibBootstrap.delegatecallBootstrapFunction(
|
||||||
address(ownable),
|
address(features.ownable),
|
||||||
abi.encodeWithSelector(ownable.bootstrap.selector, address(ownable))
|
abi.encodeWithSelector(
|
||||||
|
Ownable.bootstrap.selector
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Transfer ownership to the real owner.
|
// Transfer ownership to the real owner.
|
||||||
|
@ -28,10 +28,13 @@ library LibStorage {
|
|||||||
uint256 private constant STORAGE_SLOT_EXP = 128;
|
uint256 private constant STORAGE_SLOT_EXP = 128;
|
||||||
|
|
||||||
/// @dev Storage IDs for feature storage buckets.
|
/// @dev Storage IDs for feature storage buckets.
|
||||||
|
/// WARNING: APPEND-ONLY.
|
||||||
enum StorageId {
|
enum StorageId {
|
||||||
Proxy,
|
Proxy,
|
||||||
SimpleFunctionRegistry,
|
SimpleFunctionRegistry,
|
||||||
Ownable
|
Ownable,
|
||||||
|
TokenSpender,
|
||||||
|
TransformERC20
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Get the storage slot given a storage ID. We assign unique, well-spaced
|
/// @dev Get the storage slot given a storage ID. We assign unique, well-spaced
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "./LibStorage.sol";
|
||||||
|
import "../external/IAllowanceTarget.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Storage helpers for the `TokenSpender` feature.
|
||||||
|
library LibTokenSpenderStorage {
|
||||||
|
|
||||||
|
/// @dev Storage bucket for this feature.
|
||||||
|
struct Storage {
|
||||||
|
// Allowance target contract.
|
||||||
|
IAllowanceTarget allowanceTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Get the storage bucket for this contract.
|
||||||
|
function getStorage() internal pure returns (Storage storage stor) {
|
||||||
|
uint256 storageSlot = LibStorage.getStorageSlot(
|
||||||
|
LibStorage.StorageId.TokenSpender
|
||||||
|
);
|
||||||
|
assembly { stor_slot := storageSlot }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "./LibStorage.sol";
|
||||||
|
import "../external/IFlashWallet.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Storage helpers for the `TokenSpender` feature.
|
||||||
|
library LibTransformERC20Storage {
|
||||||
|
|
||||||
|
/// @dev Storage bucket for this feature.
|
||||||
|
struct Storage {
|
||||||
|
// The current wallet instance.
|
||||||
|
IFlashWallet wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Get the storage bucket for this contract.
|
||||||
|
function getStorage() internal pure returns (Storage storage stor) {
|
||||||
|
uint256 storageSlot = LibStorage.getStorageSlot(
|
||||||
|
LibStorage.StorageId.TransformERC20
|
||||||
|
);
|
||||||
|
assembly { stor_slot := storageSlot }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev A transformation callback used in `TransformERC20.transformERC20()`.
|
||||||
|
interface IERC20Transformer {
|
||||||
|
|
||||||
|
/// @dev Called from `TransformERC20.transformERC20()`. This will be
|
||||||
|
/// delegatecalled in the context of the FlashWallet instance being used.
|
||||||
|
/// @param callDataHash The hash of the `TransformERC20.transformERC20()` calldata.
|
||||||
|
/// @param taker The taker address (caller of `TransformERC20.transformERC20()`).
|
||||||
|
/// @param data Arbitrary data to pass to the transformer.
|
||||||
|
/// @return rlpDeploymentNonce RLP-encoded deployment nonce of the deployer
|
||||||
|
/// when this transformer was deployed. This is used to verify that
|
||||||
|
/// this transformer was deployed by a trusted contract.
|
||||||
|
function transform(
|
||||||
|
bytes32 callDataHash,
|
||||||
|
address payable taker,
|
||||||
|
bytes calldata data
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes memory rlpDeploymentNonce);
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
library LibERC20Transformer {
|
||||||
|
|
||||||
|
/// @dev ETH pseudo-token address.
|
||||||
|
address constant internal ETH_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||||
|
|
||||||
|
using LibERC20TokenV06 for IERC20TokenV06;
|
||||||
|
|
||||||
|
/// @dev Transfer ERC20 tokens and ETH.
|
||||||
|
/// @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
|
||||||
|
{
|
||||||
|
if (isTokenETH(token)) {
|
||||||
|
to.transfer(amount);
|
||||||
|
} else {
|
||||||
|
token.compatTransfer(to, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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)
|
||||||
|
{
|
||||||
|
return address(token) == ETH_TOKEN_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Check the balance of an ERC20 token or ETH.
|
||||||
|
/// @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)
|
||||||
|
{
|
||||||
|
return isTokenETH(token) ? owner.balance : token.balanceOf(owner);
|
||||||
|
}
|
||||||
|
}
|
51
contracts/zero-ex/contracts/test/TestCallTarget.sol
Normal file
51
contracts/zero-ex/contracts/test/TestCallTarget.sol
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
|
||||||
|
contract TestCallTarget {
|
||||||
|
|
||||||
|
event CallTargetCalled(
|
||||||
|
address context,
|
||||||
|
address sender,
|
||||||
|
bytes data,
|
||||||
|
uint256 value
|
||||||
|
);
|
||||||
|
|
||||||
|
bytes4 private constant MAGIC_BYTES = 0x12345678;
|
||||||
|
bytes private constant REVERTING_DATA = hex"1337";
|
||||||
|
|
||||||
|
fallback() external payable {
|
||||||
|
if (keccak256(msg.data) == keccak256(REVERTING_DATA)) {
|
||||||
|
revert("TestCallTarget/REVERT");
|
||||||
|
}
|
||||||
|
emit CallTargetCalled(
|
||||||
|
address(this),
|
||||||
|
msg.sender,
|
||||||
|
msg.data,
|
||||||
|
msg.value
|
||||||
|
);
|
||||||
|
bytes4 rval = MAGIC_BYTES;
|
||||||
|
assembly {
|
||||||
|
mstore(0, rval)
|
||||||
|
return(0, 32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
contracts/zero-ex/contracts/test/TestFullMigration.sol
Normal file
38
contracts/zero-ex/contracts/test/TestFullMigration.sol
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "../src/ZeroEx.sol";
|
||||||
|
import "../src/features/IBootstrap.sol";
|
||||||
|
import "../src/migrations/FullMigration.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestFullMigration is
|
||||||
|
FullMigration
|
||||||
|
{
|
||||||
|
address public dieRecipient;
|
||||||
|
|
||||||
|
// solhint-disable-next-line no-empty-blocks
|
||||||
|
constructor(address payable deployer) public FullMigration(deployer) {}
|
||||||
|
|
||||||
|
function die(address payable ethRecipient) external override {
|
||||||
|
dieRecipient = ethRecipient;
|
||||||
|
}
|
||||||
|
}
|
@ -37,12 +37,12 @@ contract TestInitialMigration is
|
|||||||
IBootstrap(address(zeroEx)).bootstrap(address(this), new bytes(0));
|
IBootstrap(address(zeroEx)).bootstrap(address(this), new bytes(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCodeSizeOf(address target) external view returns (uint256 codeSize) {
|
function bootstrap(address owner, BootstrapFeatures memory features)
|
||||||
assembly { codeSize := extcodesize(target) }
|
public
|
||||||
}
|
override
|
||||||
|
returns (bytes4 success)
|
||||||
function bootstrap(address owner) public override returns (bytes4 success) {
|
{
|
||||||
success = InitialMigration.bootstrap(owner);
|
success = InitialMigration.bootstrap(owner, features);
|
||||||
// Snoop the bootstrap feature contract.
|
// Snoop the bootstrap feature contract.
|
||||||
bootstrapFeature = ZeroEx(address(uint160(address(this))))
|
bootstrapFeature = ZeroEx(address(uint160(address(this))))
|
||||||
.getFunctionImplementation(IBootstrap.bootstrap.selector);
|
.getFunctionImplementation(IBootstrap.bootstrap.selector);
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
import "../src/transformers/IERC20Transformer.sol";
|
||||||
|
import "../src/transformers/LibERC20Transformer.sol";
|
||||||
|
import "./TestMintableERC20Token.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestMintTokenERC20Transformer is
|
||||||
|
IERC20Transformer
|
||||||
|
{
|
||||||
|
struct TransformData {
|
||||||
|
IERC20TokenV06 inputToken;
|
||||||
|
TestMintableERC20Token outputToken;
|
||||||
|
uint256 burnAmount;
|
||||||
|
uint256 mintAmount;
|
||||||
|
uint256 feeAmount;
|
||||||
|
bytes deploymentNonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
event MintTransform(
|
||||||
|
address context,
|
||||||
|
address caller,
|
||||||
|
bytes32 callDataHash,
|
||||||
|
address taker,
|
||||||
|
bytes data,
|
||||||
|
uint256 inputTokenBalance,
|
||||||
|
uint256 ethBalance
|
||||||
|
);
|
||||||
|
|
||||||
|
function transform(
|
||||||
|
bytes32 callDataHash,
|
||||||
|
address payable taker,
|
||||||
|
bytes calldata data_
|
||||||
|
)
|
||||||
|
external
|
||||||
|
override
|
||||||
|
returns (bytes memory rlpDeploymentNonce)
|
||||||
|
{
|
||||||
|
TransformData memory data = abi.decode(data_, (TransformData));
|
||||||
|
emit MintTransform(
|
||||||
|
address(this),
|
||||||
|
msg.sender,
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
data_,
|
||||||
|
data.inputToken.balanceOf(address(this)),
|
||||||
|
address(this).balance
|
||||||
|
);
|
||||||
|
// "Burn" input tokens.
|
||||||
|
data.inputToken.transfer(address(0), data.burnAmount);
|
||||||
|
// Mint output tokens.
|
||||||
|
if (LibERC20Transformer.isTokenETH(IERC20TokenV06(address(data.outputToken)))) {
|
||||||
|
taker.transfer(data.mintAmount);
|
||||||
|
} else {
|
||||||
|
data.outputToken.mint(
|
||||||
|
taker,
|
||||||
|
data.mintAmount
|
||||||
|
);
|
||||||
|
// Burn fees from output.
|
||||||
|
data.outputToken.burn(taker, data.feeAmount);
|
||||||
|
}
|
||||||
|
return data.deploymentNonce;
|
||||||
|
}
|
||||||
|
}
|
77
contracts/zero-ex/contracts/test/TestMintableERC20Token.sol
Normal file
77
contracts/zero-ex/contracts/test/TestMintableERC20Token.sol
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
|
||||||
|
contract TestMintableERC20Token {
|
||||||
|
|
||||||
|
mapping(address => uint256) public balanceOf;
|
||||||
|
mapping(address => mapping(address => uint256)) public allowance;
|
||||||
|
|
||||||
|
function transfer(address to, uint256 amount)
|
||||||
|
external
|
||||||
|
virtual
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return transferFrom(msg.sender, to, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function approve(address spender, uint256 amount)
|
||||||
|
external
|
||||||
|
virtual
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
allowance[msg.sender][spender] = amount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mint(address owner, uint256 amount)
|
||||||
|
external
|
||||||
|
virtual
|
||||||
|
{
|
||||||
|
balanceOf[owner] += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function burn(address owner, uint256 amount)
|
||||||
|
external
|
||||||
|
virtual
|
||||||
|
{
|
||||||
|
require(balanceOf[owner] >= amount, "TestMintableERC20Token/INSUFFICIENT_FUNDS");
|
||||||
|
balanceOf[owner] -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferFrom(address from, address to, uint256 amount)
|
||||||
|
public
|
||||||
|
virtual
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
if (from != msg.sender) {
|
||||||
|
require(
|
||||||
|
allowance[from][msg.sender] >= amount,
|
||||||
|
"TestMintableERC20Token/INSUFFICIENT_ALLOWANCE"
|
||||||
|
);
|
||||||
|
allowance[from][msg.sender] -= amount;
|
||||||
|
}
|
||||||
|
require(balanceOf[from] >= amount, "TestMintableERC20Token/INSUFFICIENT_FUNDS");
|
||||||
|
balanceOf[from] -= amount;
|
||||||
|
balanceOf[to] += amount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
30
contracts/zero-ex/contracts/test/TestTokenSpender.sol
Normal file
30
contracts/zero-ex/contracts/test/TestTokenSpender.sol
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "../src/features/TokenSpender.sol";
|
||||||
|
|
||||||
|
contract TestTokenSpender is
|
||||||
|
TokenSpender
|
||||||
|
{
|
||||||
|
modifier onlySelf() override {
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "./TestMintableERC20Token.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestTokenSpenderERC20Token is
|
||||||
|
TestMintableERC20Token
|
||||||
|
{
|
||||||
|
|
||||||
|
event TransferFromCalled(
|
||||||
|
address sender,
|
||||||
|
address from,
|
||||||
|
address to,
|
||||||
|
uint256 amount
|
||||||
|
);
|
||||||
|
|
||||||
|
// `transferFrom()` behavior depends on the value of `amount`.
|
||||||
|
uint256 constant private EMPTY_RETURN_AMOUNT = 1337;
|
||||||
|
uint256 constant private FALSE_RETURN_AMOUNT = 1338;
|
||||||
|
uint256 constant private REVERT_RETURN_AMOUNT = 1339;
|
||||||
|
|
||||||
|
function transferFrom(address from, address to, uint256 amount)
|
||||||
|
public
|
||||||
|
override
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
emit TransferFromCalled(msg.sender, from, to, amount);
|
||||||
|
if (amount == EMPTY_RETURN_AMOUNT) {
|
||||||
|
assembly { return(0, 0) }
|
||||||
|
}
|
||||||
|
if (amount == FALSE_RETURN_AMOUNT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amount == REVERT_RETURN_AMOUNT) {
|
||||||
|
revert("TestTokenSpenderERC20Token/Revert");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBalanceAndAllowanceOf(
|
||||||
|
address owner,
|
||||||
|
uint256 balance,
|
||||||
|
address spender,
|
||||||
|
uint256 allowance_
|
||||||
|
)
|
||||||
|
external
|
||||||
|
{
|
||||||
|
balanceOf[owner] = balance;
|
||||||
|
allowance[owner][spender] = allowance_;
|
||||||
|
}
|
||||||
|
}
|
37
contracts/zero-ex/contracts/test/TestTransformERC20.sol
Normal file
37
contracts/zero-ex/contracts/test/TestTransformERC20.sol
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "../src/features/TransformERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestTransformERC20 is
|
||||||
|
TransformERC20
|
||||||
|
{
|
||||||
|
// solhint-disable no-empty-blocks
|
||||||
|
constructor(address trustedDeployer)
|
||||||
|
TransformERC20(trustedDeployer)
|
||||||
|
public
|
||||||
|
{}
|
||||||
|
|
||||||
|
modifier onlySelf() override {
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
@ -32,15 +32,15 @@
|
|||||||
"test:circleci": "yarn test",
|
"test:circleci": "yarn test",
|
||||||
"contracts:gen": "contracts-gen generate",
|
"contracts:gen": "contracts-gen generate",
|
||||||
"contracts:copy": "contracts-gen copy",
|
"contracts:copy": "contracts-gen copy",
|
||||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
|
"lint-contracts": "#solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
|
||||||
"compile:truffle": "truffle compile",
|
"compile:truffle": "truffle compile",
|
||||||
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
|
"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"
|
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "ZeroEx,IOwnable,ISimpleFunctionRegistry",
|
"publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(Bootstrap|FixinCommon|IBootstrap|IFeature|IOwnable|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|InitialMigration|LibBootstrap|LibCommonRichErrors|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|Ownable|SimpleFunctionRegistry|TestInitialMigration|TestMigrator|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestZeroExFeature|ZeroEx).json"
|
"abis": "./test/generated-artifacts/@(AllowanceTarget|Bootstrap|FixinCommon|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Transformer|IFeature|IFlashWallet|IOwnable|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|Ownable|SimpleFunctionRegistry|TestCallTarget|TestFullMigration|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestZeroExFeature|TokenSpender|TransformERC20|ZeroEx).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -62,6 +62,7 @@
|
|||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/mocha": "^5.2.7",
|
"@types/mocha": "^5.2.7",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
"mocha": "^6.2.0",
|
"mocha": "^6.2.0",
|
||||||
"npm-run-all": "^4.1.2",
|
"npm-run-all": "^4.1.2",
|
||||||
"shx": "^0.2.2",
|
"shx": "^0.2.2",
|
||||||
@ -76,7 +77,9 @@
|
|||||||
"@0x/types": "^3.1.2",
|
"@0x/types": "^3.1.2",
|
||||||
"@0x/typescript-typings": "^5.0.2",
|
"@0x/typescript-typings": "^5.0.2",
|
||||||
"@0x/utils": "^5.4.1",
|
"@0x/utils": "^5.4.1",
|
||||||
"ethereum-types": "^3.1.0"
|
"@0x/web3-wrapper": "^7.0.7",
|
||||||
|
"ethereum-types": "^3.1.0",
|
||||||
|
"ethereumjs-util": "^5.1.1"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
@ -5,11 +5,25 @@
|
|||||||
*/
|
*/
|
||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
|
import * as FullMigration from '../generated-artifacts/FullMigration.json';
|
||||||
|
import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json';
|
||||||
|
import * as IERC20Transformer from '../generated-artifacts/IERC20Transformer.json';
|
||||||
|
import * as IFlashWallet from '../generated-artifacts/IFlashWallet.json';
|
||||||
|
import * as InitialMigration from '../generated-artifacts/InitialMigration.json';
|
||||||
import * as IOwnable from '../generated-artifacts/IOwnable.json';
|
import * as IOwnable from '../generated-artifacts/IOwnable.json';
|
||||||
import * as ISimpleFunctionRegistry from '../generated-artifacts/ISimpleFunctionRegistry.json';
|
import * as ISimpleFunctionRegistry from '../generated-artifacts/ISimpleFunctionRegistry.json';
|
||||||
|
import * as ITokenSpender from '../generated-artifacts/ITokenSpender.json';
|
||||||
|
import * as ITransformERC20 from '../generated-artifacts/ITransformERC20.json';
|
||||||
import * as ZeroEx from '../generated-artifacts/ZeroEx.json';
|
import * as ZeroEx from '../generated-artifacts/ZeroEx.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
ZeroEx: ZeroEx as ContractArtifact,
|
ZeroEx: ZeroEx as ContractArtifact,
|
||||||
|
FullMigration: FullMigration as ContractArtifact,
|
||||||
|
InitialMigration: InitialMigration as ContractArtifact,
|
||||||
|
IFlashWallet: IFlashWallet as ContractArtifact,
|
||||||
|
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
|
||||||
|
IERC20Transformer: IERC20Transformer as ContractArtifact,
|
||||||
IOwnable: IOwnable as ContractArtifact,
|
IOwnable: IOwnable as ContractArtifact,
|
||||||
ISimpleFunctionRegistry: ISimpleFunctionRegistry as ContractArtifact,
|
ISimpleFunctionRegistry: ISimpleFunctionRegistry as ContractArtifact,
|
||||||
|
ITokenSpender: ITokenSpender as ContractArtifact,
|
||||||
|
ITransformERC20: ITransformERC20 as ContractArtifact,
|
||||||
};
|
};
|
||||||
|
@ -36,3 +36,4 @@ export {
|
|||||||
TupleDataItem,
|
TupleDataItem,
|
||||||
StateMutability,
|
StateMutability,
|
||||||
} from 'ethereum-types';
|
} from 'ethereum-types';
|
||||||
|
export { rlpEncodeNonce } from './nonce_utils';
|
||||||
|
25
contracts/zero-ex/src/nonce_utils.ts
Normal file
25
contracts/zero-ex/src/nonce_utils.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { hexUtils } from '@0x/utils';
|
||||||
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
|
import * as ethjs from 'ethereumjs-util';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch and RLP encode the transaction count (nonce) of an account.
|
||||||
|
*/
|
||||||
|
export async function getRLPEncodedAccountNonceAsync(web3Wrapper: Web3Wrapper, address: string): Promise<string> {
|
||||||
|
const nonce = await web3Wrapper.getAccountNonceAsync(address);
|
||||||
|
return rlpEncodeNonce(nonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RLP encode the transaction count (nonce) of an account.
|
||||||
|
*/
|
||||||
|
export function rlpEncodeNonce(nonce: number): string {
|
||||||
|
if (nonce === 0) {
|
||||||
|
return '0x80';
|
||||||
|
} else if (nonce <= 0x7f) {
|
||||||
|
return ethjs.bufferToHex(ethjs.toBuffer(nonce));
|
||||||
|
} else {
|
||||||
|
const rlpNonce = ethjs.bufferToHex(ethjs.toBuffer(nonce));
|
||||||
|
return hexUtils.concat(rlpNonce.length + 0x80, rlpNonce);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,13 @@
|
|||||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
export * from '../generated-wrappers/full_migration';
|
||||||
|
export * from '../generated-wrappers/i_allowance_target';
|
||||||
|
export * from '../generated-wrappers/i_erc20_transformer';
|
||||||
|
export * from '../generated-wrappers/i_flash_wallet';
|
||||||
export * from '../generated-wrappers/i_ownable';
|
export * from '../generated-wrappers/i_ownable';
|
||||||
export * from '../generated-wrappers/i_simple_function_registry';
|
export * from '../generated-wrappers/i_simple_function_registry';
|
||||||
|
export * from '../generated-wrappers/i_token_spender';
|
||||||
|
export * from '../generated-wrappers/i_transform_erc20';
|
||||||
|
export * from '../generated-wrappers/initial_migration';
|
||||||
export * from '../generated-wrappers/zero_ex';
|
export * from '../generated-wrappers/zero_ex';
|
||||||
|
82
contracts/zero-ex/test/allowance_target_test.ts
Normal file
82
contracts/zero-ex/test/allowance_target_test.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { blockchainTests, constants, expect, randomAddress, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||||
|
import { AuthorizableRevertErrors, hexUtils, StringRevertError } from '@0x/utils';
|
||||||
|
|
||||||
|
import { artifacts } from './artifacts';
|
||||||
|
import { AllowanceTargetContract, TestCallTargetContract, TestCallTargetEvents } from './wrappers';
|
||||||
|
|
||||||
|
blockchainTests.resets('AllowanceTarget', env => {
|
||||||
|
let owner: string;
|
||||||
|
let authority: string;
|
||||||
|
let allowanceTarget: AllowanceTargetContract;
|
||||||
|
let callTarget: TestCallTargetContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
[owner, authority] = await env.getAccountAddressesAsync();
|
||||||
|
allowanceTarget = await AllowanceTargetContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.AllowanceTarget,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
await allowanceTarget.addAuthorizedAddress(authority).awaitTransactionSuccessAsync();
|
||||||
|
callTarget = await TestCallTargetContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestCallTarget,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678');
|
||||||
|
const REVERTING_DATA = '0x1337';
|
||||||
|
|
||||||
|
describe('executeCall()', () => {
|
||||||
|
it('non-authority cannot call executeCall()', async () => {
|
||||||
|
const notAuthority = randomAddress();
|
||||||
|
const tx = allowanceTarget
|
||||||
|
.executeCall(randomAddress(), hexUtils.random())
|
||||||
|
.callAsync({ from: notAuthority });
|
||||||
|
return expect(tx).to.revertWith(new AuthorizableRevertErrors.SenderNotAuthorizedError(notAuthority));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('authority can call executeCall()', async () => {
|
||||||
|
const targetData = hexUtils.random(128);
|
||||||
|
const receipt = await allowanceTarget
|
||||||
|
.executeCall(callTarget.address, targetData)
|
||||||
|
.awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
context: callTarget.address,
|
||||||
|
sender: allowanceTarget.address,
|
||||||
|
data: targetData,
|
||||||
|
value: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestCallTargetEvents.CallTargetCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('AllowanceTarget returns call result', async () => {
|
||||||
|
const result = await allowanceTarget
|
||||||
|
.executeCall(callTarget.address, hexUtils.random(128))
|
||||||
|
.callAsync({ from: authority });
|
||||||
|
expect(result).to.eq(TARGET_RETURN_VALUE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('AllowanceTarget returns raw call revert', async () => {
|
||||||
|
const tx = allowanceTarget.executeCall(callTarget.address, REVERTING_DATA).callAsync({ from: authority });
|
||||||
|
return expect(tx).to.revertWith(new StringRevertError('TestCallTarget/REVERT'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('AllowanceTarget cannot receive ETH', async () => {
|
||||||
|
const tx = env.web3Wrapper.sendTransactionAsync({
|
||||||
|
to: allowanceTarget.address,
|
||||||
|
from: owner,
|
||||||
|
value: 0,
|
||||||
|
});
|
||||||
|
return expect(tx).to.eventually.be.rejected();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -5,16 +5,25 @@
|
|||||||
*/
|
*/
|
||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
|
import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.json';
|
||||||
import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json';
|
import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json';
|
||||||
import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json';
|
import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json';
|
||||||
|
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
|
||||||
|
import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
|
||||||
|
import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json';
|
||||||
import * as IBootstrap from '../test/generated-artifacts/IBootstrap.json';
|
import * as IBootstrap from '../test/generated-artifacts/IBootstrap.json';
|
||||||
|
import * as IERC20Transformer from '../test/generated-artifacts/IERC20Transformer.json';
|
||||||
import * as IFeature from '../test/generated-artifacts/IFeature.json';
|
import * as IFeature from '../test/generated-artifacts/IFeature.json';
|
||||||
|
import * as IFlashWallet from '../test/generated-artifacts/IFlashWallet.json';
|
||||||
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
|
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
|
||||||
import * as IOwnable from '../test/generated-artifacts/IOwnable.json';
|
import * as IOwnable from '../test/generated-artifacts/IOwnable.json';
|
||||||
import * as ISimpleFunctionRegistry from '../test/generated-artifacts/ISimpleFunctionRegistry.json';
|
import * as ISimpleFunctionRegistry from '../test/generated-artifacts/ISimpleFunctionRegistry.json';
|
||||||
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
|
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
|
||||||
|
import * as ITokenSpender from '../test/generated-artifacts/ITokenSpender.json';
|
||||||
|
import * as ITransformERC20 from '../test/generated-artifacts/ITransformERC20.json';
|
||||||
import * as LibBootstrap from '../test/generated-artifacts/LibBootstrap.json';
|
import * as LibBootstrap from '../test/generated-artifacts/LibBootstrap.json';
|
||||||
import * as LibCommonRichErrors from '../test/generated-artifacts/LibCommonRichErrors.json';
|
import * as LibCommonRichErrors from '../test/generated-artifacts/LibCommonRichErrors.json';
|
||||||
|
import * as LibERC20Transformer from '../test/generated-artifacts/LibERC20Transformer.json';
|
||||||
import * as LibMigrate from '../test/generated-artifacts/LibMigrate.json';
|
import * as LibMigrate from '../test/generated-artifacts/LibMigrate.json';
|
||||||
import * as LibOwnableRichErrors from '../test/generated-artifacts/LibOwnableRichErrors.json';
|
import * as LibOwnableRichErrors from '../test/generated-artifacts/LibOwnableRichErrors.json';
|
||||||
import * as LibOwnableStorage from '../test/generated-artifacts/LibOwnableStorage.json';
|
import * as LibOwnableStorage from '../test/generated-artifacts/LibOwnableStorage.json';
|
||||||
@ -22,14 +31,28 @@ import * as LibProxyRichErrors from '../test/generated-artifacts/LibProxyRichErr
|
|||||||
import * as LibProxyStorage from '../test/generated-artifacts/LibProxyStorage.json';
|
import * as LibProxyStorage from '../test/generated-artifacts/LibProxyStorage.json';
|
||||||
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
|
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
|
||||||
import * as LibSimpleFunctionRegistryStorage from '../test/generated-artifacts/LibSimpleFunctionRegistryStorage.json';
|
import * as LibSimpleFunctionRegistryStorage from '../test/generated-artifacts/LibSimpleFunctionRegistryStorage.json';
|
||||||
|
import * as LibSpenderRichErrors from '../test/generated-artifacts/LibSpenderRichErrors.json';
|
||||||
import * as LibStorage from '../test/generated-artifacts/LibStorage.json';
|
import * as LibStorage from '../test/generated-artifacts/LibStorage.json';
|
||||||
|
import * as LibTokenSpenderStorage from '../test/generated-artifacts/LibTokenSpenderStorage.json';
|
||||||
|
import * as LibTransformERC20RichErrors from '../test/generated-artifacts/LibTransformERC20RichErrors.json';
|
||||||
|
import * as LibTransformERC20Storage from '../test/generated-artifacts/LibTransformERC20Storage.json';
|
||||||
|
import * as LibWalletRichErrors from '../test/generated-artifacts/LibWalletRichErrors.json';
|
||||||
import * as Ownable from '../test/generated-artifacts/Ownable.json';
|
import * as Ownable from '../test/generated-artifacts/Ownable.json';
|
||||||
import * as SimpleFunctionRegistry from '../test/generated-artifacts/SimpleFunctionRegistry.json';
|
import * as SimpleFunctionRegistry from '../test/generated-artifacts/SimpleFunctionRegistry.json';
|
||||||
|
import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json';
|
||||||
|
import * as TestFullMigration from '../test/generated-artifacts/TestFullMigration.json';
|
||||||
import * as TestInitialMigration from '../test/generated-artifacts/TestInitialMigration.json';
|
import * as TestInitialMigration from '../test/generated-artifacts/TestInitialMigration.json';
|
||||||
import * as TestMigrator from '../test/generated-artifacts/TestMigrator.json';
|
import * as TestMigrator from '../test/generated-artifacts/TestMigrator.json';
|
||||||
|
import * as TestMintableERC20Token from '../test/generated-artifacts/TestMintableERC20Token.json';
|
||||||
|
import * as TestMintTokenERC20Transformer from '../test/generated-artifacts/TestMintTokenERC20Transformer.json';
|
||||||
import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json';
|
import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json';
|
||||||
import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json';
|
import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json';
|
||||||
|
import * as TestTokenSpender from '../test/generated-artifacts/TestTokenSpender.json';
|
||||||
|
import * as TestTokenSpenderERC20Token from '../test/generated-artifacts/TestTokenSpenderERC20Token.json';
|
||||||
|
import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformERC20.json';
|
||||||
import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeature.json';
|
import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeature.json';
|
||||||
|
import * as TokenSpender from '../test/generated-artifacts/TokenSpender.json';
|
||||||
|
import * as TransformERC20 from '../test/generated-artifacts/TransformERC20.json';
|
||||||
import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json';
|
import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
ZeroEx: ZeroEx as ContractArtifact,
|
ZeroEx: ZeroEx as ContractArtifact,
|
||||||
@ -37,14 +60,26 @@ export const artifacts = {
|
|||||||
LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
|
LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
|
||||||
LibProxyRichErrors: LibProxyRichErrors as ContractArtifact,
|
LibProxyRichErrors: LibProxyRichErrors as ContractArtifact,
|
||||||
LibSimpleFunctionRegistryRichErrors: LibSimpleFunctionRegistryRichErrors as ContractArtifact,
|
LibSimpleFunctionRegistryRichErrors: LibSimpleFunctionRegistryRichErrors as ContractArtifact,
|
||||||
|
LibSpenderRichErrors: LibSpenderRichErrors as ContractArtifact,
|
||||||
|
LibTransformERC20RichErrors: LibTransformERC20RichErrors as ContractArtifact,
|
||||||
|
LibWalletRichErrors: LibWalletRichErrors as ContractArtifact,
|
||||||
|
AllowanceTarget: AllowanceTarget as ContractArtifact,
|
||||||
|
FlashWallet: FlashWallet as ContractArtifact,
|
||||||
|
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
|
||||||
|
IFlashWallet: IFlashWallet as ContractArtifact,
|
||||||
Bootstrap: Bootstrap as ContractArtifact,
|
Bootstrap: Bootstrap as ContractArtifact,
|
||||||
IBootstrap: IBootstrap as ContractArtifact,
|
IBootstrap: IBootstrap as ContractArtifact,
|
||||||
IFeature: IFeature as ContractArtifact,
|
IFeature: IFeature as ContractArtifact,
|
||||||
IOwnable: IOwnable as ContractArtifact,
|
IOwnable: IOwnable as ContractArtifact,
|
||||||
ISimpleFunctionRegistry: ISimpleFunctionRegistry as ContractArtifact,
|
ISimpleFunctionRegistry: ISimpleFunctionRegistry as ContractArtifact,
|
||||||
|
ITokenSpender: ITokenSpender as ContractArtifact,
|
||||||
|
ITransformERC20: ITransformERC20 as ContractArtifact,
|
||||||
Ownable: Ownable as ContractArtifact,
|
Ownable: Ownable as ContractArtifact,
|
||||||
SimpleFunctionRegistry: SimpleFunctionRegistry as ContractArtifact,
|
SimpleFunctionRegistry: SimpleFunctionRegistry as ContractArtifact,
|
||||||
|
TokenSpender: TokenSpender as ContractArtifact,
|
||||||
|
TransformERC20: TransformERC20 as ContractArtifact,
|
||||||
FixinCommon: FixinCommon as ContractArtifact,
|
FixinCommon: FixinCommon as ContractArtifact,
|
||||||
|
FullMigration: FullMigration as ContractArtifact,
|
||||||
InitialMigration: InitialMigration as ContractArtifact,
|
InitialMigration: InitialMigration as ContractArtifact,
|
||||||
LibBootstrap: LibBootstrap as ContractArtifact,
|
LibBootstrap: LibBootstrap as ContractArtifact,
|
||||||
LibMigrate: LibMigrate as ContractArtifact,
|
LibMigrate: LibMigrate as ContractArtifact,
|
||||||
@ -52,10 +87,21 @@ export const artifacts = {
|
|||||||
LibProxyStorage: LibProxyStorage as ContractArtifact,
|
LibProxyStorage: LibProxyStorage as ContractArtifact,
|
||||||
LibSimpleFunctionRegistryStorage: LibSimpleFunctionRegistryStorage as ContractArtifact,
|
LibSimpleFunctionRegistryStorage: LibSimpleFunctionRegistryStorage as ContractArtifact,
|
||||||
LibStorage: LibStorage as ContractArtifact,
|
LibStorage: LibStorage as ContractArtifact,
|
||||||
|
LibTokenSpenderStorage: LibTokenSpenderStorage as ContractArtifact,
|
||||||
|
LibTransformERC20Storage: LibTransformERC20Storage as ContractArtifact,
|
||||||
|
IERC20Transformer: IERC20Transformer as ContractArtifact,
|
||||||
|
LibERC20Transformer: LibERC20Transformer as ContractArtifact,
|
||||||
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
|
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
|
||||||
|
TestCallTarget: TestCallTarget as ContractArtifact,
|
||||||
|
TestFullMigration: TestFullMigration as ContractArtifact,
|
||||||
TestInitialMigration: TestInitialMigration as ContractArtifact,
|
TestInitialMigration: TestInitialMigration as ContractArtifact,
|
||||||
TestMigrator: TestMigrator as ContractArtifact,
|
TestMigrator: TestMigrator as ContractArtifact,
|
||||||
|
TestMintTokenERC20Transformer: TestMintTokenERC20Transformer as ContractArtifact,
|
||||||
|
TestMintableERC20Token: TestMintableERC20Token as ContractArtifact,
|
||||||
TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact,
|
TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact,
|
||||||
TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact,
|
TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact,
|
||||||
|
TestTokenSpender: TestTokenSpender as ContractArtifact,
|
||||||
|
TestTokenSpenderERC20Token: TestTokenSpenderERC20Token as ContractArtifact,
|
||||||
|
TestTransformERC20: TestTransformERC20 as ContractArtifact,
|
||||||
TestZeroExFeature: TestZeroExFeature as ContractArtifact,
|
TestZeroExFeature: TestZeroExFeature as ContractArtifact,
|
||||||
};
|
};
|
||||||
|
141
contracts/zero-ex/test/features/token_spender_test.ts
Normal file
141
contracts/zero-ex/test/features/token_spender_test.ts
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import {
|
||||||
|
blockchainTests,
|
||||||
|
expect,
|
||||||
|
getRandomInteger,
|
||||||
|
randomAddress,
|
||||||
|
verifyEventsFromLogs,
|
||||||
|
} from '@0x/contracts-test-utils';
|
||||||
|
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
||||||
|
|
||||||
|
import { artifacts } from '../artifacts';
|
||||||
|
import { abis } from '../utils/abis';
|
||||||
|
import { fullMigrateAsync } from '../utils/migration';
|
||||||
|
import {
|
||||||
|
TestTokenSpenderERC20TokenContract,
|
||||||
|
TestTokenSpenderERC20TokenEvents,
|
||||||
|
TokenSpenderContract,
|
||||||
|
ZeroExContract,
|
||||||
|
} from '../wrappers';
|
||||||
|
|
||||||
|
blockchainTests.resets('TokenSpender feature', env => {
|
||||||
|
let zeroEx: ZeroExContract;
|
||||||
|
let feature: TokenSpenderContract;
|
||||||
|
let token: TestTokenSpenderERC20TokenContract;
|
||||||
|
let allowanceTarget: string;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const [owner] = await env.getAccountAddressesAsync();
|
||||||
|
zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, {
|
||||||
|
tokenSpender: await TokenSpenderContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestTokenSpender,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
feature = new TokenSpenderContract(zeroEx.address, env.provider, env.txDefaults, abis);
|
||||||
|
token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestTokenSpenderERC20Token,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
allowanceTarget = await feature.getAllowanceTarget().callAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_spendERC20Tokens()', () => {
|
||||||
|
const EMPTY_RETURN_AMOUNT = 1337;
|
||||||
|
const FALSE_RETURN_AMOUNT = 1338;
|
||||||
|
const REVERT_RETURN_AMOUNT = 1339;
|
||||||
|
|
||||||
|
it('_spendERC20Tokens() successfully calls compliant ERC20 token', async () => {
|
||||||
|
const tokenFrom = randomAddress();
|
||||||
|
const tokenTo = randomAddress();
|
||||||
|
const tokenAmount = new BigNumber(123456);
|
||||||
|
const receipt = await feature
|
||||||
|
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
|
.awaitTransactionSuccessAsync();
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
sender: allowanceTarget,
|
||||||
|
from: tokenFrom,
|
||||||
|
to: tokenTo,
|
||||||
|
amount: tokenAmount,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('_spendERC20Tokens() successfully calls non-compliant ERC20 token', async () => {
|
||||||
|
const tokenFrom = randomAddress();
|
||||||
|
const tokenTo = randomAddress();
|
||||||
|
const tokenAmount = new BigNumber(EMPTY_RETURN_AMOUNT);
|
||||||
|
const receipt = await feature
|
||||||
|
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
|
.awaitTransactionSuccessAsync();
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
sender: allowanceTarget,
|
||||||
|
from: tokenFrom,
|
||||||
|
to: tokenTo,
|
||||||
|
amount: tokenAmount,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('_spendERC20Tokens() reverts if ERC20 token reverts', async () => {
|
||||||
|
const tokenFrom = randomAddress();
|
||||||
|
const tokenTo = randomAddress();
|
||||||
|
const tokenAmount = new BigNumber(REVERT_RETURN_AMOUNT);
|
||||||
|
const tx = feature
|
||||||
|
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
|
.awaitTransactionSuccessAsync();
|
||||||
|
const expectedError = new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
||||||
|
token.address,
|
||||||
|
tokenFrom,
|
||||||
|
tokenTo,
|
||||||
|
tokenAmount,
|
||||||
|
new StringRevertError('TestTokenSpenderERC20Token/Revert').encode(),
|
||||||
|
);
|
||||||
|
return expect(tx).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('_spendERC20Tokens() reverts if ERC20 token returns false', async () => {
|
||||||
|
const tokenFrom = randomAddress();
|
||||||
|
const tokenTo = randomAddress();
|
||||||
|
const tokenAmount = new BigNumber(FALSE_RETURN_AMOUNT);
|
||||||
|
const tx = feature
|
||||||
|
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
|
.awaitTransactionSuccessAsync();
|
||||||
|
return expect(tx).to.revertWith(
|
||||||
|
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
||||||
|
token.address,
|
||||||
|
tokenFrom,
|
||||||
|
tokenTo,
|
||||||
|
tokenAmount,
|
||||||
|
hexUtils.leftPad(0),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getSpendableERC20BalanceOf()', () => {
|
||||||
|
it("returns the minimum of the owner's balance and allowance", async () => {
|
||||||
|
const balance = getRandomInteger(1, '1e18');
|
||||||
|
const allowance = getRandomInteger(1, '1e18');
|
||||||
|
const tokenOwner = randomAddress();
|
||||||
|
await token
|
||||||
|
.setBalanceAndAllowanceOf(tokenOwner, balance, allowanceTarget, allowance)
|
||||||
|
.awaitTransactionSuccessAsync();
|
||||||
|
const spendableBalance = await feature.getSpendableERC20BalanceOf(token.address, tokenOwner).callAsync();
|
||||||
|
expect(spendableBalance).to.bignumber.eq(BigNumber.min(balance, allowance));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
526
contracts/zero-ex/test/features/transform_erc20_test.ts
Normal file
526
contracts/zero-ex/test/features/transform_erc20_test.ts
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
import {
|
||||||
|
blockchainTests,
|
||||||
|
constants,
|
||||||
|
expect,
|
||||||
|
getRandomInteger,
|
||||||
|
getRandomPortion,
|
||||||
|
Numberish,
|
||||||
|
randomAddress,
|
||||||
|
verifyEventsFromLogs,
|
||||||
|
} from '@0x/contracts-test-utils';
|
||||||
|
import { AbiEncoder, hexUtils, ZeroExRevertErrors } from '@0x/utils';
|
||||||
|
|
||||||
|
import { getRLPEncodedAccountNonceAsync } from '../../src/nonce_utils';
|
||||||
|
import { artifacts } from '../artifacts';
|
||||||
|
import { abis } from '../utils/abis';
|
||||||
|
import { fullMigrateAsync } from '../utils/migration';
|
||||||
|
import {
|
||||||
|
FlashWalletContract,
|
||||||
|
ITokenSpenderContract,
|
||||||
|
TestMintableERC20TokenContract,
|
||||||
|
TestMintTokenERC20TransformerContract,
|
||||||
|
TestMintTokenERC20TransformerEvents,
|
||||||
|
TransformERC20Contract,
|
||||||
|
TransformERC20Events,
|
||||||
|
ZeroExContract,
|
||||||
|
} from '../wrappers';
|
||||||
|
|
||||||
|
blockchainTests.resets('TransformERC20 feature', env => {
|
||||||
|
let taker: string;
|
||||||
|
let transformerDeployer: string;
|
||||||
|
let zeroEx: ZeroExContract;
|
||||||
|
let feature: TransformERC20Contract;
|
||||||
|
let wallet: FlashWalletContract;
|
||||||
|
let allowanceTarget: string;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
let owner;
|
||||||
|
[owner, taker, transformerDeployer] = await env.getAccountAddressesAsync();
|
||||||
|
zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, {
|
||||||
|
transformERC20: await TransformERC20Contract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestTransformERC20,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
transformerDeployer,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
feature = new TransformERC20Contract(zeroEx.address, env.provider, env.txDefaults, abis);
|
||||||
|
wallet = new FlashWalletContract(await feature.getTransformWallet().callAsync(), env.provider, env.txDefaults);
|
||||||
|
allowanceTarget = await new ITokenSpenderContract(zeroEx.address, env.provider, env.txDefaults)
|
||||||
|
.getAllowanceTarget()
|
||||||
|
.callAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
const { MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } = constants;
|
||||||
|
|
||||||
|
describe('wallets', () => {
|
||||||
|
it('createTransformWallet() replaces the current wallet', async () => {
|
||||||
|
const newWalletAddress = await feature.createTransformWallet().callAsync();
|
||||||
|
expect(newWalletAddress).to.not.eq(wallet.address);
|
||||||
|
await feature.createTransformWallet().awaitTransactionSuccessAsync();
|
||||||
|
return expect(feature.getTransformWallet().callAsync()).to.eventually.eq(newWalletAddress);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_transformERC20()', () => {
|
||||||
|
let inputToken: TestMintableERC20TokenContract;
|
||||||
|
let outputToken: TestMintableERC20TokenContract;
|
||||||
|
let mintTransformer: TestMintTokenERC20TransformerContract;
|
||||||
|
let rlpNonce: string;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
inputToken = await TestMintableERC20TokenContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestMintableERC20Token,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
outputToken = await TestMintableERC20TokenContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestMintableERC20Token,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
rlpNonce = await getRLPEncodedAccountNonceAsync(env.web3Wrapper, transformerDeployer);
|
||||||
|
mintTransformer = await TestMintTokenERC20TransformerContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestMintTokenERC20Transformer,
|
||||||
|
env.provider,
|
||||||
|
{
|
||||||
|
...env.txDefaults,
|
||||||
|
from: transformerDeployer,
|
||||||
|
},
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
await inputToken.approve(allowanceTarget, MAX_UINT256).awaitTransactionSuccessAsync({ from: taker });
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Transformation {
|
||||||
|
transformer: string;
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transformDataEncoder = AbiEncoder.create([
|
||||||
|
{
|
||||||
|
name: 'data',
|
||||||
|
type: 'tuple',
|
||||||
|
components: [
|
||||||
|
{ name: 'inputToken', type: 'address' },
|
||||||
|
{ name: 'outputToken', type: 'address' },
|
||||||
|
{ name: 'burnAmount', type: 'uint256' },
|
||||||
|
{ name: 'mintAmount', type: 'uint256' },
|
||||||
|
{ name: 'feeAmount', type: 'uint256' },
|
||||||
|
{ name: 'deploymentNonce', type: 'bytes' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
function createMintTokenTransformation(
|
||||||
|
opts: Partial<{
|
||||||
|
transformer: string;
|
||||||
|
outputTokenAddress: string;
|
||||||
|
inputTokenAddress: string;
|
||||||
|
inputTokenBurnAmunt: Numberish;
|
||||||
|
outputTokenMintAmount: Numberish;
|
||||||
|
outputTokenFeeAmount: Numberish;
|
||||||
|
rlpNonce: string;
|
||||||
|
}> = {},
|
||||||
|
): Transformation {
|
||||||
|
const _opts = {
|
||||||
|
rlpNonce,
|
||||||
|
outputTokenAddress: outputToken.address,
|
||||||
|
inputTokenAddress: inputToken.address,
|
||||||
|
inputTokenBurnAmunt: ZERO_AMOUNT,
|
||||||
|
outputTokenMintAmount: ZERO_AMOUNT,
|
||||||
|
outputTokenFeeAmount: ZERO_AMOUNT,
|
||||||
|
transformer: mintTransformer.address,
|
||||||
|
...opts,
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
transformer: _opts.transformer,
|
||||||
|
data: transformDataEncoder.encode([
|
||||||
|
{
|
||||||
|
inputToken: _opts.inputTokenAddress,
|
||||||
|
outputToken: _opts.outputTokenAddress,
|
||||||
|
burnAmount: _opts.inputTokenBurnAmunt,
|
||||||
|
mintAmount: _opts.outputTokenMintAmount,
|
||||||
|
feeAmount: _opts.outputTokenFeeAmount,
|
||||||
|
deploymentNonce: _opts.rlpNonce,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it("succeeds if taker's output token balance increases by exactly minOutputTokenAmount", async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(1, '1e18');
|
||||||
|
const outputTokenMintAmount = minOutputTokenAmount;
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
const transformation = createMintTokenTransformation({
|
||||||
|
outputTokenMintAmount,
|
||||||
|
inputTokenBurnAmunt: inputTokenAmount,
|
||||||
|
});
|
||||||
|
const receipt = await feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
[transformation],
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
taker,
|
||||||
|
inputTokenAmount,
|
||||||
|
outputTokenAmount: outputTokenMintAmount,
|
||||||
|
inputToken: inputToken.address,
|
||||||
|
outputToken: outputToken.address,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TransformERC20Events.TransformedERC20,
|
||||||
|
);
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
context: wallet.address,
|
||||||
|
caller: zeroEx.address,
|
||||||
|
data: transformation.data,
|
||||||
|
inputTokenBalance: inputTokenAmount,
|
||||||
|
ethBalance: callValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestMintTokenERC20TransformerEvents.MintTransform,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const ETH_TOKEN_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
||||||
|
|
||||||
|
it("succeeds if taker's output token balance increases by exactly minOutputTokenAmount, with ETH", async () => {
|
||||||
|
const startingInputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(1, '1e18');
|
||||||
|
const outputTokenMintAmount = minOutputTokenAmount;
|
||||||
|
const callValue = outputTokenMintAmount.times(2);
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
const transformation = createMintTokenTransformation({
|
||||||
|
outputTokenMintAmount,
|
||||||
|
inputTokenBurnAmunt: inputTokenAmount,
|
||||||
|
outputTokenAddress: ETH_TOKEN_ADDRESS,
|
||||||
|
});
|
||||||
|
const startingOutputTokenBalance = await env.web3Wrapper.getBalanceInWeiAsync(taker);
|
||||||
|
const receipt = await feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
ETH_TOKEN_ADDRESS,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
[transformation],
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
taker,
|
||||||
|
inputTokenAmount,
|
||||||
|
outputTokenAmount: outputTokenMintAmount,
|
||||||
|
inputToken: inputToken.address,
|
||||||
|
outputToken: ETH_TOKEN_ADDRESS,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TransformERC20Events.TransformedERC20,
|
||||||
|
);
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
context: wallet.address,
|
||||||
|
caller: zeroEx.address,
|
||||||
|
data: transformation.data,
|
||||||
|
inputTokenBalance: inputTokenAmount,
|
||||||
|
ethBalance: callValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestMintTokenERC20TransformerEvents.MintTransform,
|
||||||
|
);
|
||||||
|
expect(await env.web3Wrapper.getBalanceInWeiAsync(taker)).to.bignumber.eq(
|
||||||
|
startingOutputTokenBalance.plus(outputTokenMintAmount),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("succeeds if taker's output token balance increases by more than minOutputTokenAmount", async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(1, '1e18');
|
||||||
|
const outputTokenMintAmount = minOutputTokenAmount.plus(1);
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
const transformation = createMintTokenTransformation({
|
||||||
|
outputTokenMintAmount,
|
||||||
|
inputTokenBurnAmunt: inputTokenAmount,
|
||||||
|
});
|
||||||
|
const receipt = await feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
[transformation],
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
taker,
|
||||||
|
inputTokenAmount,
|
||||||
|
outputTokenAmount: outputTokenMintAmount,
|
||||||
|
inputToken: inputToken.address,
|
||||||
|
outputToken: outputToken.address,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TransformERC20Events.TransformedERC20,
|
||||||
|
);
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
context: wallet.address,
|
||||||
|
caller: zeroEx.address,
|
||||||
|
data: transformation.data,
|
||||||
|
inputTokenBalance: inputTokenAmount,
|
||||||
|
ethBalance: callValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestMintTokenERC20TransformerEvents.MintTransform,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws if taker's output token balance increases by less than minOutputTokenAmount", async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(1, '1e18');
|
||||||
|
const outputTokenMintAmount = minOutputTokenAmount.minus(1);
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const tx = feature
|
||||||
|
._transformERC20(
|
||||||
|
hexUtils.random(),
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
[
|
||||||
|
createMintTokenTransformation({
|
||||||
|
outputTokenMintAmount,
|
||||||
|
inputTokenBurnAmunt: inputTokenAmount,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
const expectedError = new ZeroExRevertErrors.TransformERC20.IncompleteTransformERC20Error(
|
||||||
|
outputToken.address,
|
||||||
|
outputTokenMintAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
);
|
||||||
|
return expect(tx).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws if taker's output token balance decreases", async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = ZERO_AMOUNT;
|
||||||
|
const outputTokenFeeAmount = 1;
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const tx = feature
|
||||||
|
._transformERC20(
|
||||||
|
hexUtils.random(),
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
[
|
||||||
|
createMintTokenTransformation({
|
||||||
|
outputTokenFeeAmount,
|
||||||
|
inputTokenBurnAmunt: inputTokenAmount,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
const expectedError = new ZeroExRevertErrors.TransformERC20.NegativeTransformERC20OutputError(
|
||||||
|
outputToken.address,
|
||||||
|
outputTokenFeeAmount,
|
||||||
|
);
|
||||||
|
return expect(tx).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can call multiple transformers', async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(2, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(2, '1e18');
|
||||||
|
const outputTokenMintAmount = minOutputTokenAmount;
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
// Split the total minting between two transformers.
|
||||||
|
const transformations = [
|
||||||
|
createMintTokenTransformation({
|
||||||
|
inputTokenBurnAmunt: 1,
|
||||||
|
outputTokenMintAmount: 1,
|
||||||
|
}),
|
||||||
|
createMintTokenTransformation({
|
||||||
|
inputTokenBurnAmunt: inputTokenAmount.minus(1),
|
||||||
|
outputTokenMintAmount: outputTokenMintAmount.minus(1),
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
const receipt = await feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
transformations,
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
context: wallet.address,
|
||||||
|
caller: zeroEx.address,
|
||||||
|
data: transformations[0].data,
|
||||||
|
inputTokenBalance: inputTokenAmount,
|
||||||
|
ethBalance: callValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
context: wallet.address,
|
||||||
|
caller: zeroEx.address,
|
||||||
|
data: transformations[1].data,
|
||||||
|
inputTokenBalance: inputTokenAmount.minus(1),
|
||||||
|
ethBalance: callValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestMintTokenERC20TransformerEvents.MintTransform,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails with third-party transformer', async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(2, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(2, '1e18');
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
const transformations = [createMintTokenTransformation({ transformer: randomAddress() })];
|
||||||
|
const tx = feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
transformations,
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
return expect(tx).to.revertWith(new ZeroExRevertErrors.TransformERC20.InvalidRLPNonceError(NULL_BYTES));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails with incorrect transformer RLP nonce', async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(2, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(2, '1e18');
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
const badRlpNonce = '0x00';
|
||||||
|
const transformations = [createMintTokenTransformation({ rlpNonce: badRlpNonce })];
|
||||||
|
const tx = feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
transformations,
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
return expect(tx).to.revertWith(
|
||||||
|
new ZeroExRevertErrors.TransformERC20.UnauthorizedTransformerError(
|
||||||
|
transformations[0].transformer,
|
||||||
|
badRlpNonce,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails with invalid transformer RLP nonce', async () => {
|
||||||
|
const startingOutputTokenBalance = getRandomInteger(0, '100e18');
|
||||||
|
const startingInputTokenBalance = getRandomInteger(2, '100e18');
|
||||||
|
await outputToken.mint(taker, startingOutputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
|
||||||
|
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
|
||||||
|
const minOutputTokenAmount = getRandomInteger(2, '1e18');
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const callDataHash = hexUtils.random();
|
||||||
|
const badRlpNonce = '0x010203040506';
|
||||||
|
const transformations = [createMintTokenTransformation({ rlpNonce: badRlpNonce })];
|
||||||
|
const tx = feature
|
||||||
|
._transformERC20(
|
||||||
|
callDataHash,
|
||||||
|
taker,
|
||||||
|
inputToken.address,
|
||||||
|
outputToken.address,
|
||||||
|
inputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
transformations,
|
||||||
|
)
|
||||||
|
.awaitTransactionSuccessAsync({ value: callValue });
|
||||||
|
return expect(tx).to.revertWith(new ZeroExRevertErrors.TransformERC20.InvalidRLPNonceError(badRlpNonce));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
211
contracts/zero-ex/test/flash_wallet_test.ts
Normal file
211
contracts/zero-ex/test/flash_wallet_test.ts
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import {
|
||||||
|
blockchainTests,
|
||||||
|
constants,
|
||||||
|
expect,
|
||||||
|
getRandomInteger,
|
||||||
|
randomAddress,
|
||||||
|
verifyEventsFromLogs,
|
||||||
|
} from '@0x/contracts-test-utils';
|
||||||
|
import { hexUtils, OwnableRevertErrors, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
||||||
|
|
||||||
|
import { artifacts } from './artifacts';
|
||||||
|
import { FlashWalletContract, TestCallTargetContract, TestCallTargetEvents } from './wrappers';
|
||||||
|
|
||||||
|
blockchainTests.resets('FlashWallet', env => {
|
||||||
|
let owner: string;
|
||||||
|
let wallet: FlashWalletContract;
|
||||||
|
let callTarget: TestCallTargetContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
[owner] = await env.getAccountAddressesAsync();
|
||||||
|
wallet = await FlashWalletContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.FlashWallet,
|
||||||
|
env.provider,
|
||||||
|
{
|
||||||
|
...env.txDefaults,
|
||||||
|
from: owner,
|
||||||
|
},
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
callTarget = await TestCallTargetContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestCallTarget,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678');
|
||||||
|
const REVERTING_DATA = '0x1337';
|
||||||
|
|
||||||
|
it('owned by deployer', () => {
|
||||||
|
return expect(wallet.owner().callAsync()).to.eventually.eq(owner);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('executeCall()', () => {
|
||||||
|
it('non-owner cannot call executeCall()', async () => {
|
||||||
|
const notOwner = randomAddress();
|
||||||
|
const tx = wallet
|
||||||
|
.executeCall(randomAddress(), hexUtils.random(), getRandomInteger(0, '100e18'))
|
||||||
|
.callAsync({ from: notOwner });
|
||||||
|
return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('owner can call executeCall()', async () => {
|
||||||
|
const targetData = hexUtils.random(128);
|
||||||
|
const receipt = await wallet
|
||||||
|
.executeCall(callTarget.address, targetData, constants.ZERO_AMOUNT)
|
||||||
|
.awaitTransactionSuccessAsync({ from: owner });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
context: callTarget.address,
|
||||||
|
sender: wallet.address,
|
||||||
|
data: targetData,
|
||||||
|
value: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestCallTargetEvents.CallTargetCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('owner can call executeCall() with attached ETH', async () => {
|
||||||
|
const targetData = hexUtils.random(128);
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const receipt = await wallet
|
||||||
|
.executeCall(callTarget.address, targetData, callValue)
|
||||||
|
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
context: callTarget.address,
|
||||||
|
sender: wallet.address,
|
||||||
|
data: targetData,
|
||||||
|
value: callValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestCallTargetEvents.CallTargetCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('owner can call executeCall() can transfer less ETH than attached', async () => {
|
||||||
|
const targetData = hexUtils.random(128);
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const receipt = await wallet
|
||||||
|
.executeCall(callTarget.address, targetData, callValue.minus(1))
|
||||||
|
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
context: callTarget.address,
|
||||||
|
sender: wallet.address,
|
||||||
|
data: targetData,
|
||||||
|
value: callValue.minus(1),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestCallTargetEvents.CallTargetCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wallet returns call result', async () => {
|
||||||
|
const result = await wallet
|
||||||
|
.executeCall(callTarget.address, hexUtils.random(128), constants.ZERO_AMOUNT)
|
||||||
|
.callAsync({ from: owner });
|
||||||
|
expect(result).to.eq(TARGET_RETURN_VALUE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wallet wraps call revert', async () => {
|
||||||
|
const tx = wallet
|
||||||
|
.executeCall(callTarget.address, REVERTING_DATA, constants.ZERO_AMOUNT)
|
||||||
|
.callAsync({ from: owner });
|
||||||
|
return expect(tx).to.revertWith(
|
||||||
|
new ZeroExRevertErrors.Wallet.WalletExecuteCallFailedError(
|
||||||
|
wallet.address,
|
||||||
|
callTarget.address,
|
||||||
|
REVERTING_DATA,
|
||||||
|
constants.ZERO_AMOUNT,
|
||||||
|
new StringRevertError('TestCallTarget/REVERT').encode(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wallet can receive ETH', async () => {
|
||||||
|
await env.web3Wrapper.sendTransactionAsync({
|
||||||
|
to: wallet.address,
|
||||||
|
from: owner,
|
||||||
|
value: 1,
|
||||||
|
});
|
||||||
|
const bal = await env.web3Wrapper.getBalanceInWeiAsync(wallet.address);
|
||||||
|
expect(bal).to.bignumber.eq(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('executeDelegateCall()', () => {
|
||||||
|
it('non-owner cannot call executeDelegateCall()', async () => {
|
||||||
|
const notOwner = randomAddress();
|
||||||
|
const tx = wallet.executeDelegateCall(randomAddress(), hexUtils.random()).callAsync({ from: notOwner });
|
||||||
|
return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('owner can call executeDelegateCall()', async () => {
|
||||||
|
const targetData = hexUtils.random(128);
|
||||||
|
const receipt = await wallet
|
||||||
|
.executeDelegateCall(callTarget.address, targetData)
|
||||||
|
.awaitTransactionSuccessAsync({ from: owner });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
context: wallet.address,
|
||||||
|
sender: owner,
|
||||||
|
data: targetData,
|
||||||
|
value: constants.ZERO_AMOUNT,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestCallTargetEvents.CallTargetCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('executeDelegateCall() is payable', async () => {
|
||||||
|
const targetData = hexUtils.random(128);
|
||||||
|
const callValue = getRandomInteger(1, '1e18');
|
||||||
|
const receipt = await wallet
|
||||||
|
.executeDelegateCall(callTarget.address, targetData)
|
||||||
|
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
context: wallet.address,
|
||||||
|
sender: owner,
|
||||||
|
data: targetData,
|
||||||
|
value: callValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
TestCallTargetEvents.CallTargetCalled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wallet returns call result', async () => {
|
||||||
|
const result = await wallet
|
||||||
|
.executeDelegateCall(callTarget.address, hexUtils.random(128))
|
||||||
|
.callAsync({ from: owner });
|
||||||
|
expect(result).to.eq(TARGET_RETURN_VALUE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wallet wraps call revert', async () => {
|
||||||
|
const tx = wallet.executeDelegateCall(callTarget.address, REVERTING_DATA).callAsync({ from: owner });
|
||||||
|
return expect(tx).to.revertWith(
|
||||||
|
new ZeroExRevertErrors.Wallet.WalletExecuteDelegateCallFailedError(
|
||||||
|
wallet.address,
|
||||||
|
callTarget.address,
|
||||||
|
REVERTING_DATA,
|
||||||
|
new StringRevertError('TestCallTarget/REVERT').encode(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
165
contracts/zero-ex/test/full_migration_test.ts
Normal file
165
contracts/zero-ex/test/full_migration_test.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import { BaseContract } from '@0x/base-contract';
|
||||||
|
import { blockchainTests, constants, expect, randomAddress } from '@0x/contracts-test-utils';
|
||||||
|
import { BigNumber, hexUtils, ZeroExRevertErrors } from '@0x/utils';
|
||||||
|
import { DataItem, MethodAbi } from 'ethereum-types';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts } from './artifacts';
|
||||||
|
import { abis } from './utils/abis';
|
||||||
|
import { deployFullFeaturesAsync, FullFeatures, toFeatureAdddresses } from './utils/migration';
|
||||||
|
import {
|
||||||
|
AllowanceTargetContract,
|
||||||
|
IOwnableContract,
|
||||||
|
ITokenSpenderContract,
|
||||||
|
ITransformERC20Contract,
|
||||||
|
TestFullMigrationContract,
|
||||||
|
ZeroExContract,
|
||||||
|
} from './wrappers';
|
||||||
|
|
||||||
|
const { NULL_ADDRESS } = constants;
|
||||||
|
|
||||||
|
blockchainTests.resets('Full migration', env => {
|
||||||
|
let owner: string;
|
||||||
|
let zeroEx: ZeroExContract;
|
||||||
|
let features: FullFeatures;
|
||||||
|
let migrator: TestFullMigrationContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
[owner] = await env.getAccountAddressesAsync();
|
||||||
|
features = await deployFullFeaturesAsync(env.provider, env.txDefaults);
|
||||||
|
migrator = await TestFullMigrationContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestFullMigration,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
env.txDefaults.from as string,
|
||||||
|
);
|
||||||
|
const deployCall = migrator.deploy(owner, toFeatureAdddresses(features));
|
||||||
|
zeroEx = new ZeroExContract(await deployCall.callAsync(), env.provider, env.txDefaults);
|
||||||
|
await deployCall.awaitTransactionSuccessAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ZeroEx has the correct owner', async () => {
|
||||||
|
const ownable = new IOwnableContract(zeroEx.address, env.provider, env.txDefaults);
|
||||||
|
const actualOwner = await ownable.owner().callAsync();
|
||||||
|
expect(actualOwner).to.eq(owner);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('FullMigration contract self-destructs', async () => {
|
||||||
|
const dieRecipient = await migrator.dieRecipient().callAsync();
|
||||||
|
expect(dieRecipient).to.eq(owner);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Non-deployer cannot call deploy()', async () => {
|
||||||
|
const notDeployer = randomAddress();
|
||||||
|
const tx = migrator.deploy(owner, toFeatureAdddresses(features)).callAsync({ from: notDeployer });
|
||||||
|
return expect(tx).to.revertWith('FullMigration/INVALID_SENDER');
|
||||||
|
});
|
||||||
|
|
||||||
|
const FEATURE_FNS = {
|
||||||
|
TokenSpender: {
|
||||||
|
contractType: ITokenSpenderContract,
|
||||||
|
fns: ['_spendERC20Tokens'],
|
||||||
|
},
|
||||||
|
TransformERC20: {
|
||||||
|
contractType: ITransformERC20Contract,
|
||||||
|
fns: ['transformERC20', '_transformERC20', 'createTransformWallet', 'getTransformWallet'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createFakeInputs(inputs: DataItem[] | DataItem): any | any[] {
|
||||||
|
if ((inputs as DataItem[]).length !== undefined) {
|
||||||
|
return (inputs as DataItem[]).map(i => createFakeInputs(i));
|
||||||
|
}
|
||||||
|
const item = inputs as DataItem;
|
||||||
|
// TODO(dorothy-zbornak): Support fixed-length arrays.
|
||||||
|
if (/\[]$/.test(item.type)) {
|
||||||
|
return _.times(_.random(0, 8), () =>
|
||||||
|
createFakeInputs({
|
||||||
|
...item,
|
||||||
|
type: item.type.substring(0, item.type.length - 2),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (/^tuple$/.test(item.type)) {
|
||||||
|
const tuple = {} as any;
|
||||||
|
for (const comp of item.components as DataItem[]) {
|
||||||
|
tuple[comp.name] = createFakeInputs(comp);
|
||||||
|
}
|
||||||
|
return tuple;
|
||||||
|
}
|
||||||
|
if (item.type === 'address') {
|
||||||
|
return randomAddress();
|
||||||
|
}
|
||||||
|
if (item.type === 'byte') {
|
||||||
|
return hexUtils.random(1);
|
||||||
|
}
|
||||||
|
if (/^bytes$/.test(item.type)) {
|
||||||
|
return hexUtils.random(_.random(0, 128));
|
||||||
|
}
|
||||||
|
if (/^bytes\d+$/.test(item.type)) {
|
||||||
|
return hexUtils.random(parseInt(/\d+$/.exec(item.type)![0], 10));
|
||||||
|
}
|
||||||
|
if (/^uint\d+$/.test(item.type)) {
|
||||||
|
return new BigNumber(hexUtils.random(parseInt(/\d+$/.exec(item.type)![0], 10) / 8));
|
||||||
|
}
|
||||||
|
if (/^int\d+$/.test(item.type)) {
|
||||||
|
return new BigNumber(hexUtils.random(parseInt(/\d+$/.exec(item.type)![0], 10) / 8))
|
||||||
|
.div(2)
|
||||||
|
.times(_.sample([-1, 1])!);
|
||||||
|
}
|
||||||
|
throw new Error(`Unhandled input type: '${item.type}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [featureName, featureInfo] of Object.entries(FEATURE_FNS)) {
|
||||||
|
describe(`${featureName} feature`, () => {
|
||||||
|
let contract: BaseContract & { getSelector(name: string): string };
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
contract = new featureInfo.contractType(zeroEx.address, env.provider, env.txDefaults, abis);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const fn of featureInfo.fns) {
|
||||||
|
it(`${fn} is registered`, async () => {
|
||||||
|
const selector = contract.getSelector(fn);
|
||||||
|
const impl = await zeroEx.getFunctionImplementation(selector).callAsync();
|
||||||
|
expect(impl).to.not.eq(NULL_ADDRESS);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fn.startsWith('_')) {
|
||||||
|
it(`${fn} cannot be called from outside`, async () => {
|
||||||
|
const method = contract.abi.find(
|
||||||
|
d => d.type === 'function' && (d as MethodAbi).name === fn,
|
||||||
|
) as MethodAbi;
|
||||||
|
const inputs = createFakeInputs(method.inputs);
|
||||||
|
const tx = (contract as any)[fn](...inputs).callAsync();
|
||||||
|
return expect(tx).to.revertWith(
|
||||||
|
new ZeroExRevertErrors.Common.OnlyCallableBySelfError(env.txDefaults.from),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("TokenSpender's allowance target", () => {
|
||||||
|
let allowanceTarget: AllowanceTargetContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const contract = new ITokenSpenderContract(zeroEx.address, env.provider, env.txDefaults);
|
||||||
|
allowanceTarget = new AllowanceTargetContract(
|
||||||
|
await contract.getAllowanceTarget().callAsync(),
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is owned by owner', async () => {
|
||||||
|
return expect(allowanceTarget.owner().callAsync()).to.become(owner);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proxy is authorized', async () => {
|
||||||
|
return expect(allowanceTarget.authorized(zeroEx.address).callAsync()).to.become(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -2,6 +2,7 @@ import { blockchainTests, expect, randomAddress } from '@0x/contracts-test-utils
|
|||||||
import { ZeroExRevertErrors } from '@0x/utils';
|
import { ZeroExRevertErrors } from '@0x/utils';
|
||||||
|
|
||||||
import { artifacts } from './artifacts';
|
import { artifacts } from './artifacts';
|
||||||
|
import { BootstrapFeatures, deployBootstrapFeaturesAsync, toFeatureAdddresses } from './utils/migration';
|
||||||
import {
|
import {
|
||||||
IBootstrapContract,
|
IBootstrapContract,
|
||||||
InitialMigrationContract,
|
InitialMigrationContract,
|
||||||
@ -15,9 +16,11 @@ blockchainTests.resets('Initial migration', env => {
|
|||||||
let zeroEx: ZeroExContract;
|
let zeroEx: ZeroExContract;
|
||||||
let migrator: TestInitialMigrationContract;
|
let migrator: TestInitialMigrationContract;
|
||||||
let bootstrapFeature: IBootstrapContract;
|
let bootstrapFeature: IBootstrapContract;
|
||||||
|
let features: BootstrapFeatures;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
[owner] = await env.getAccountAddressesAsync();
|
[owner] = await env.getAccountAddressesAsync();
|
||||||
|
features = await deployBootstrapFeaturesAsync(env.provider, env.txDefaults);
|
||||||
migrator = await TestInitialMigrationContract.deployFrom0xArtifactAsync(
|
migrator = await TestInitialMigrationContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.TestInitialMigration,
|
artifacts.TestInitialMigration,
|
||||||
env.provider,
|
env.provider,
|
||||||
@ -31,7 +34,7 @@ blockchainTests.resets('Initial migration', env => {
|
|||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
const deployCall = migrator.deploy(owner);
|
const deployCall = migrator.deploy(owner, toFeatureAdddresses(features));
|
||||||
zeroEx = new ZeroExContract(await deployCall.callAsync(), env.provider, env.txDefaults);
|
zeroEx = new ZeroExContract(await deployCall.callAsync(), env.provider, env.txDefaults);
|
||||||
await deployCall.awaitTransactionSuccessAsync();
|
await deployCall.awaitTransactionSuccessAsync();
|
||||||
});
|
});
|
||||||
@ -43,7 +46,7 @@ blockchainTests.resets('Initial migration', env => {
|
|||||||
|
|
||||||
it('Non-deployer cannot call deploy()', async () => {
|
it('Non-deployer cannot call deploy()', async () => {
|
||||||
const notDeployer = randomAddress();
|
const notDeployer = randomAddress();
|
||||||
const tx = migrator.deploy(owner).callAsync({ from: notDeployer });
|
const tx = migrator.deploy(owner, toFeatureAdddresses(features)).callAsync({ from: notDeployer });
|
||||||
return expect(tx).to.revertWith('InitialMigration/INVALID_SENDER');
|
return expect(tx).to.revertWith('InitialMigration/INVALID_SENDER');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -67,8 +70,8 @@ blockchainTests.resets('Initial migration', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Bootstrap feature self destructs after deployment', async () => {
|
it('Bootstrap feature self destructs after deployment', async () => {
|
||||||
const codeSize = await migrator.getCodeSizeOf(bootstrapFeature.address).callAsync();
|
const doesExist = await env.web3Wrapper.doesContractExistAtAddressAsync(bootstrapFeature.address);
|
||||||
expect(codeSize).to.bignumber.eq(0);
|
expect(doesExist).to.eq(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
5
contracts/zero-ex/test/utils/abis.ts
Normal file
5
contracts/zero-ex/test/utils/abis.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts } from '../artifacts';
|
||||||
|
|
||||||
|
export const abis = _.mapValues(artifacts, v => v.compilerOutput.abi);
|
@ -1,15 +1,53 @@
|
|||||||
|
import { BaseContract } from '@0x/base-contract';
|
||||||
import { SupportedProvider } from '@0x/subproviders';
|
import { SupportedProvider } from '@0x/subproviders';
|
||||||
import { TxData } from 'ethereum-types';
|
import { TxData } from 'ethereum-types';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import { InitialMigrationContract, ZeroExContract } from '../wrappers';
|
import {
|
||||||
|
FullMigrationContract,
|
||||||
|
InitialMigrationContract,
|
||||||
|
OwnableContract,
|
||||||
|
SimpleFunctionRegistryContract,
|
||||||
|
TokenSpenderContract,
|
||||||
|
TransformERC20Contract,
|
||||||
|
ZeroExContract,
|
||||||
|
} from '../wrappers';
|
||||||
|
|
||||||
// tslint:disable: completed-docs
|
// tslint:disable: completed-docs
|
||||||
|
|
||||||
|
export interface BootstrapFeatures {
|
||||||
|
registry: SimpleFunctionRegistryContract;
|
||||||
|
ownable: OwnableContract;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deployBootstrapFeaturesAsync(
|
||||||
|
provider: SupportedProvider,
|
||||||
|
txDefaults: Partial<TxData>,
|
||||||
|
features: Partial<BootstrapFeatures> = {},
|
||||||
|
): Promise<BootstrapFeatures> {
|
||||||
|
return {
|
||||||
|
registry:
|
||||||
|
features.registry ||
|
||||||
|
(await SimpleFunctionRegistryContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.SimpleFunctionRegistry,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
artifacts,
|
||||||
|
)),
|
||||||
|
ownable:
|
||||||
|
features.ownable ||
|
||||||
|
(await OwnableContract.deployFrom0xArtifactAsync(artifacts.Ownable, provider, txDefaults, artifacts)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function initialMigrateAsync(
|
export async function initialMigrateAsync(
|
||||||
owner: string,
|
owner: string,
|
||||||
provider: SupportedProvider,
|
provider: SupportedProvider,
|
||||||
txDefaults: Partial<TxData>,
|
txDefaults: Partial<TxData>,
|
||||||
|
features: Partial<BootstrapFeatures> = {},
|
||||||
): Promise<ZeroExContract> {
|
): Promise<ZeroExContract> {
|
||||||
|
const _features = await deployBootstrapFeaturesAsync(provider, txDefaults, features);
|
||||||
const migrator = await InitialMigrationContract.deployFrom0xArtifactAsync(
|
const migrator = await InitialMigrationContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.InitialMigration,
|
artifacts.InitialMigration,
|
||||||
provider,
|
provider,
|
||||||
@ -17,8 +55,74 @@ export async function initialMigrateAsync(
|
|||||||
artifacts,
|
artifacts,
|
||||||
txDefaults.from as string,
|
txDefaults.from as string,
|
||||||
);
|
);
|
||||||
const deployCall = migrator.deploy(owner);
|
const deployCall = migrator.deploy(owner, toFeatureAdddresses(_features));
|
||||||
const zeroEx = new ZeroExContract(await deployCall.callAsync(), provider, {});
|
const zeroEx = new ZeroExContract(await deployCall.callAsync(), provider, {});
|
||||||
await deployCall.awaitTransactionSuccessAsync();
|
await deployCall.awaitTransactionSuccessAsync();
|
||||||
return zeroEx;
|
return zeroEx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FullFeatures extends BootstrapFeatures {
|
||||||
|
tokenSpender: TokenSpenderContract;
|
||||||
|
transformERC20: TransformERC20Contract;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FullMigrationOpts {
|
||||||
|
transformDeployer: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deployFullFeaturesAsync(
|
||||||
|
provider: SupportedProvider,
|
||||||
|
txDefaults: Partial<TxData>,
|
||||||
|
features: Partial<FullFeatures> = {},
|
||||||
|
opts: Partial<FullMigrationOpts> = {},
|
||||||
|
): Promise<FullFeatures> {
|
||||||
|
return {
|
||||||
|
...(await deployBootstrapFeaturesAsync(provider, txDefaults)),
|
||||||
|
tokenSpender:
|
||||||
|
features.tokenSpender ||
|
||||||
|
(await TokenSpenderContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TokenSpender,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
artifacts,
|
||||||
|
)),
|
||||||
|
transformERC20:
|
||||||
|
features.transformERC20 ||
|
||||||
|
(await TransformERC20Contract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TransformERC20,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
artifacts,
|
||||||
|
opts.transformDeployer || (txDefaults.from as string),
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fullMigrateAsync(
|
||||||
|
owner: string,
|
||||||
|
provider: SupportedProvider,
|
||||||
|
txDefaults: Partial<TxData>,
|
||||||
|
features: Partial<FullFeatures> = {},
|
||||||
|
opts: Partial<FullMigrationOpts> = {},
|
||||||
|
): Promise<ZeroExContract> {
|
||||||
|
const _features = await deployFullFeaturesAsync(provider, txDefaults, features, opts);
|
||||||
|
const migrator = await FullMigrationContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.FullMigration,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
artifacts,
|
||||||
|
txDefaults.from as string,
|
||||||
|
);
|
||||||
|
const deployCall = migrator.deploy(owner, toFeatureAdddresses(_features));
|
||||||
|
const zeroEx = new ZeroExContract(await deployCall.callAsync(), provider, {});
|
||||||
|
await deployCall.awaitTransactionSuccessAsync();
|
||||||
|
return zeroEx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable:space-before-function-parent one-line
|
||||||
|
export function toFeatureAdddresses<T extends BootstrapFeatures | FullFeatures | (BootstrapFeatures & FullFeatures)>(
|
||||||
|
features: T,
|
||||||
|
): { [name in keyof T]: string } {
|
||||||
|
// TS can't figure this out.
|
||||||
|
return _.mapValues(features, (c: BaseContract) => c.address) as any;
|
||||||
|
}
|
||||||
|
@ -3,16 +3,25 @@
|
|||||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
export * from '../test/generated-wrappers/allowance_target';
|
||||||
export * from '../test/generated-wrappers/bootstrap';
|
export * from '../test/generated-wrappers/bootstrap';
|
||||||
export * from '../test/generated-wrappers/fixin_common';
|
export * from '../test/generated-wrappers/fixin_common';
|
||||||
|
export * from '../test/generated-wrappers/flash_wallet';
|
||||||
|
export * from '../test/generated-wrappers/full_migration';
|
||||||
|
export * from '../test/generated-wrappers/i_allowance_target';
|
||||||
export * from '../test/generated-wrappers/i_bootstrap';
|
export * from '../test/generated-wrappers/i_bootstrap';
|
||||||
|
export * from '../test/generated-wrappers/i_erc20_transformer';
|
||||||
export * from '../test/generated-wrappers/i_feature';
|
export * from '../test/generated-wrappers/i_feature';
|
||||||
|
export * from '../test/generated-wrappers/i_flash_wallet';
|
||||||
export * from '../test/generated-wrappers/i_ownable';
|
export * from '../test/generated-wrappers/i_ownable';
|
||||||
export * from '../test/generated-wrappers/i_simple_function_registry';
|
export * from '../test/generated-wrappers/i_simple_function_registry';
|
||||||
export * from '../test/generated-wrappers/i_test_simple_function_registry_feature';
|
export * from '../test/generated-wrappers/i_test_simple_function_registry_feature';
|
||||||
|
export * from '../test/generated-wrappers/i_token_spender';
|
||||||
|
export * from '../test/generated-wrappers/i_transform_erc20';
|
||||||
export * from '../test/generated-wrappers/initial_migration';
|
export * from '../test/generated-wrappers/initial_migration';
|
||||||
export * from '../test/generated-wrappers/lib_bootstrap';
|
export * from '../test/generated-wrappers/lib_bootstrap';
|
||||||
export * from '../test/generated-wrappers/lib_common_rich_errors';
|
export * from '../test/generated-wrappers/lib_common_rich_errors';
|
||||||
|
export * from '../test/generated-wrappers/lib_erc20_transformer';
|
||||||
export * from '../test/generated-wrappers/lib_migrate';
|
export * from '../test/generated-wrappers/lib_migrate';
|
||||||
export * from '../test/generated-wrappers/lib_ownable_rich_errors';
|
export * from '../test/generated-wrappers/lib_ownable_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_ownable_storage';
|
export * from '../test/generated-wrappers/lib_ownable_storage';
|
||||||
@ -20,12 +29,26 @@ export * from '../test/generated-wrappers/lib_proxy_rich_errors';
|
|||||||
export * from '../test/generated-wrappers/lib_proxy_storage';
|
export * from '../test/generated-wrappers/lib_proxy_storage';
|
||||||
export * from '../test/generated-wrappers/lib_simple_function_registry_rich_errors';
|
export * from '../test/generated-wrappers/lib_simple_function_registry_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_simple_function_registry_storage';
|
export * from '../test/generated-wrappers/lib_simple_function_registry_storage';
|
||||||
|
export * from '../test/generated-wrappers/lib_spender_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_storage';
|
export * from '../test/generated-wrappers/lib_storage';
|
||||||
|
export * from '../test/generated-wrappers/lib_token_spender_storage';
|
||||||
|
export * from '../test/generated-wrappers/lib_transform_erc20_rich_errors';
|
||||||
|
export * from '../test/generated-wrappers/lib_transform_erc20_storage';
|
||||||
|
export * from '../test/generated-wrappers/lib_wallet_rich_errors';
|
||||||
export * from '../test/generated-wrappers/ownable';
|
export * from '../test/generated-wrappers/ownable';
|
||||||
export * from '../test/generated-wrappers/simple_function_registry';
|
export * from '../test/generated-wrappers/simple_function_registry';
|
||||||
|
export * from '../test/generated-wrappers/test_call_target';
|
||||||
|
export * from '../test/generated-wrappers/test_full_migration';
|
||||||
export * from '../test/generated-wrappers/test_initial_migration';
|
export * from '../test/generated-wrappers/test_initial_migration';
|
||||||
export * from '../test/generated-wrappers/test_migrator';
|
export * from '../test/generated-wrappers/test_migrator';
|
||||||
|
export * from '../test/generated-wrappers/test_mint_token_erc20_transformer';
|
||||||
|
export * from '../test/generated-wrappers/test_mintable_erc20_token';
|
||||||
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl1';
|
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl1';
|
||||||
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl2';
|
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl2';
|
||||||
|
export * from '../test/generated-wrappers/test_token_spender';
|
||||||
|
export * from '../test/generated-wrappers/test_token_spender_erc20_token';
|
||||||
|
export * from '../test/generated-wrappers/test_transform_erc20';
|
||||||
export * from '../test/generated-wrappers/test_zero_ex_feature';
|
export * from '../test/generated-wrappers/test_zero_ex_feature';
|
||||||
|
export * from '../test/generated-wrappers/token_spender';
|
||||||
|
export * from '../test/generated-wrappers/transform_erc20';
|
||||||
export * from '../test/generated-wrappers/zero_ex';
|
export * from '../test/generated-wrappers/zero_ex';
|
||||||
|
@ -3,19 +3,35 @@
|
|||||||
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||||
"files": [
|
"files": [
|
||||||
|
"generated-artifacts/FullMigration.json",
|
||||||
|
"generated-artifacts/IAllowanceTarget.json",
|
||||||
|
"generated-artifacts/IERC20Transformer.json",
|
||||||
|
"generated-artifacts/IFlashWallet.json",
|
||||||
"generated-artifacts/IOwnable.json",
|
"generated-artifacts/IOwnable.json",
|
||||||
"generated-artifacts/ISimpleFunctionRegistry.json",
|
"generated-artifacts/ISimpleFunctionRegistry.json",
|
||||||
|
"generated-artifacts/ITokenSpender.json",
|
||||||
|
"generated-artifacts/ITransformERC20.json",
|
||||||
|
"generated-artifacts/InitialMigration.json",
|
||||||
"generated-artifacts/ZeroEx.json",
|
"generated-artifacts/ZeroEx.json",
|
||||||
|
"test/generated-artifacts/AllowanceTarget.json",
|
||||||
"test/generated-artifacts/Bootstrap.json",
|
"test/generated-artifacts/Bootstrap.json",
|
||||||
"test/generated-artifacts/FixinCommon.json",
|
"test/generated-artifacts/FixinCommon.json",
|
||||||
|
"test/generated-artifacts/FlashWallet.json",
|
||||||
|
"test/generated-artifacts/FullMigration.json",
|
||||||
|
"test/generated-artifacts/IAllowanceTarget.json",
|
||||||
"test/generated-artifacts/IBootstrap.json",
|
"test/generated-artifacts/IBootstrap.json",
|
||||||
|
"test/generated-artifacts/IERC20Transformer.json",
|
||||||
"test/generated-artifacts/IFeature.json",
|
"test/generated-artifacts/IFeature.json",
|
||||||
|
"test/generated-artifacts/IFlashWallet.json",
|
||||||
"test/generated-artifacts/IOwnable.json",
|
"test/generated-artifacts/IOwnable.json",
|
||||||
"test/generated-artifacts/ISimpleFunctionRegistry.json",
|
"test/generated-artifacts/ISimpleFunctionRegistry.json",
|
||||||
"test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json",
|
"test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json",
|
||||||
|
"test/generated-artifacts/ITokenSpender.json",
|
||||||
|
"test/generated-artifacts/ITransformERC20.json",
|
||||||
"test/generated-artifacts/InitialMigration.json",
|
"test/generated-artifacts/InitialMigration.json",
|
||||||
"test/generated-artifacts/LibBootstrap.json",
|
"test/generated-artifacts/LibBootstrap.json",
|
||||||
"test/generated-artifacts/LibCommonRichErrors.json",
|
"test/generated-artifacts/LibCommonRichErrors.json",
|
||||||
|
"test/generated-artifacts/LibERC20Transformer.json",
|
||||||
"test/generated-artifacts/LibMigrate.json",
|
"test/generated-artifacts/LibMigrate.json",
|
||||||
"test/generated-artifacts/LibOwnableRichErrors.json",
|
"test/generated-artifacts/LibOwnableRichErrors.json",
|
||||||
"test/generated-artifacts/LibOwnableStorage.json",
|
"test/generated-artifacts/LibOwnableStorage.json",
|
||||||
@ -23,14 +39,28 @@
|
|||||||
"test/generated-artifacts/LibProxyStorage.json",
|
"test/generated-artifacts/LibProxyStorage.json",
|
||||||
"test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json",
|
"test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json",
|
||||||
"test/generated-artifacts/LibSimpleFunctionRegistryStorage.json",
|
"test/generated-artifacts/LibSimpleFunctionRegistryStorage.json",
|
||||||
|
"test/generated-artifacts/LibSpenderRichErrors.json",
|
||||||
"test/generated-artifacts/LibStorage.json",
|
"test/generated-artifacts/LibStorage.json",
|
||||||
|
"test/generated-artifacts/LibTokenSpenderStorage.json",
|
||||||
|
"test/generated-artifacts/LibTransformERC20RichErrors.json",
|
||||||
|
"test/generated-artifacts/LibTransformERC20Storage.json",
|
||||||
|
"test/generated-artifacts/LibWalletRichErrors.json",
|
||||||
"test/generated-artifacts/Ownable.json",
|
"test/generated-artifacts/Ownable.json",
|
||||||
"test/generated-artifacts/SimpleFunctionRegistry.json",
|
"test/generated-artifacts/SimpleFunctionRegistry.json",
|
||||||
|
"test/generated-artifacts/TestCallTarget.json",
|
||||||
|
"test/generated-artifacts/TestFullMigration.json",
|
||||||
"test/generated-artifacts/TestInitialMigration.json",
|
"test/generated-artifacts/TestInitialMigration.json",
|
||||||
"test/generated-artifacts/TestMigrator.json",
|
"test/generated-artifacts/TestMigrator.json",
|
||||||
|
"test/generated-artifacts/TestMintTokenERC20Transformer.json",
|
||||||
|
"test/generated-artifacts/TestMintableERC20Token.json",
|
||||||
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json",
|
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json",
|
||||||
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json",
|
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json",
|
||||||
|
"test/generated-artifacts/TestTokenSpender.json",
|
||||||
|
"test/generated-artifacts/TestTokenSpenderERC20Token.json",
|
||||||
|
"test/generated-artifacts/TestTransformERC20.json",
|
||||||
"test/generated-artifacts/TestZeroExFeature.json",
|
"test/generated-artifacts/TestZeroExFeature.json",
|
||||||
|
"test/generated-artifacts/TokenSpender.json",
|
||||||
|
"test/generated-artifacts/TransformERC20.json",
|
||||||
"test/generated-artifacts/ZeroEx.json"
|
"test/generated-artifacts/ZeroEx.json"
|
||||||
],
|
],
|
||||||
"exclude": ["./deploy/solc/solc_bin"]
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
"extends": ["@0x/tslint-config"],
|
"extends": ["@0x/tslint-config"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"custom-no-magic-numbers": false,
|
"custom-no-magic-numbers": false,
|
||||||
"max-file-line-count": false
|
"max-file-line-count": false,
|
||||||
|
"no-non-null-assertion": false,
|
||||||
|
"no-unnecessary-type-assertion": false,
|
||||||
|
"number-literal-format": false
|
||||||
},
|
},
|
||||||
"linterOptions": {
|
"linterOptions": {
|
||||||
"exclude": ["src/artifacts.ts", "test/artifacts.ts"]
|
"exclude": ["src/artifacts.ts", "test/artifacts.ts"]
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "6.1.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update ganache-core",
|
||||||
|
"pr": 2545
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1582623685,
|
"timestamp": 1582623685,
|
||||||
"version": "6.0.8",
|
"version": "6.0.8",
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
"ethereum-types": "^3.1.0",
|
"ethereum-types": "^3.1.0",
|
||||||
"ethereumjs-tx": "^1.3.5",
|
"ethereumjs-tx": "^1.3.5",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
"ganache-core": "^2.9.0-istanbul.0",
|
"ganache-core": "^2.10.2",
|
||||||
"hdkey": "^0.7.1",
|
"hdkey": "^0.7.1",
|
||||||
"json-rpc-error": "2.0.0",
|
"json-rpc-error": "2.0.0",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
{
|
{
|
||||||
"note": "`instanceof Array` => `Array.isArray`",
|
"note": "`instanceof Array` => `Array.isArray`",
|
||||||
"pr": 2567
|
"pr": 2567
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add more `ZeroExRevertErrors`",
|
||||||
|
"pr": 2545
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -49,4 +49,7 @@ export const ZeroExRevertErrors = {
|
|||||||
Proxy: require('./revert_errors/zero-ex/proxy_revert_errors'),
|
Proxy: require('./revert_errors/zero-ex/proxy_revert_errors'),
|
||||||
SimpleFunctionRegistry: require('./revert_errors/zero-ex/simple_function_registry_revert_errors'),
|
SimpleFunctionRegistry: require('./revert_errors/zero-ex/simple_function_registry_revert_errors'),
|
||||||
Ownable: require('./revert_errors/zero-ex/ownable_revert_errors'),
|
Ownable: require('./revert_errors/zero-ex/ownable_revert_errors'),
|
||||||
|
Spender: require('./revert_errors/zero-ex/spender_revert_errors'),
|
||||||
|
TransformERC20: require('./revert_errors/zero-ex/transform_erc20_revert_errors'),
|
||||||
|
Wallet: require('./revert_errors/zero-ex/wallet_revert_errors'),
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,16 @@ import { BigNumber } from './configured_bignumber';
|
|||||||
|
|
||||||
// tslint:disable: max-classes-per-file
|
// tslint:disable: max-classes-per-file
|
||||||
|
|
||||||
type ArgTypes = string | BigNumber | number | boolean | BigNumber[] | string[] | number[] | boolean[];
|
type ArgTypes =
|
||||||
|
| string
|
||||||
|
| BigNumber
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| BigNumber[]
|
||||||
|
| string[]
|
||||||
|
| number[]
|
||||||
|
| boolean[]
|
||||||
|
| Array<BigNumber | number | string>;
|
||||||
type ValueMap = ObjectMap<ArgTypes | undefined>;
|
type ValueMap = ObjectMap<ArgTypes | undefined>;
|
||||||
type RevertErrorDecoder = (hex: string) => ValueMap;
|
type RevertErrorDecoder = (hex: string) => ValueMap;
|
||||||
|
|
||||||
|
@ -9,6 +9,13 @@ export class OnlyCallableBySelfError extends RevertError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is identical to the one in utils.
|
||||||
|
// export class IllegalReentrancyError extends RevertError {
|
||||||
|
// constructor() {
|
||||||
|
// super('IllegalReentrancyError', 'IllegalReentrancyError()', {});
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const types = [OnlyCallableBySelfError];
|
const types = [OnlyCallableBySelfError];
|
||||||
|
|
||||||
// Register the types we've defined.
|
// Register the types we've defined.
|
||||||
|
@ -16,7 +16,23 @@ export class MigrateCallFailedError extends RevertError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const types = [AlreadyMigratingError, MigrateCallFailedError];
|
export class OnlyOwnerError extends RevertError {
|
||||||
|
constructor(sender?: string, owner?: string) {
|
||||||
|
super('OnlyOwnerError', 'OnlyOwnerError(address sender, bytes owner)', {
|
||||||
|
sender,
|
||||||
|
owner,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is identical to the one in utils.
|
||||||
|
// export class TransferOwnerToZeroError extends RevertError {
|
||||||
|
// constructor() {
|
||||||
|
// super('TransferOwnerToZeroError', 'TransferOwnerToZeroError()', {});
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
const types = [AlreadyMigratingError, MigrateCallFailedError, OnlyOwnerError];
|
||||||
|
|
||||||
// Register the types we've defined.
|
// Register the types we've defined.
|
||||||
for (const type of types) {
|
for (const type of types) {
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
import { RevertError } from '../../revert_error';
|
||||||
|
import { Numberish } from '../../types';
|
||||||
|
|
||||||
|
// tslint:disable:max-classes-per-file
|
||||||
|
export class SpenderERC20TransferFromFailedError extends RevertError {
|
||||||
|
constructor(token?: string, owner?: string, to?: string, amount?: Numberish, errorData?: string) {
|
||||||
|
super(
|
||||||
|
'SpenderERC20TransferFromFailedError',
|
||||||
|
'SpenderERC20TransferFromFailedError(address token, address owner, address to, uint256 amount, bytes errorData)',
|
||||||
|
{
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
to,
|
||||||
|
amount,
|
||||||
|
errorData,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const types = [SpenderERC20TransferFromFailedError];
|
||||||
|
|
||||||
|
// Register the types we've defined.
|
||||||
|
for (const type of types) {
|
||||||
|
RevertError.registerType(type);
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
import { RevertError } from '../../revert_error';
|
||||||
|
import { Numberish } from '../../types';
|
||||||
|
|
||||||
|
// tslint:disable:max-classes-per-file
|
||||||
|
export class InsufficientEthAttachedError extends RevertError {
|
||||||
|
constructor(ethAttached?: Numberish, ethNeeded?: Numberish) {
|
||||||
|
super('InsufficientEthAttachedError', 'InsufficientEthAttachedError(uint256 ethAttached, uint256 ethNeeded)', {
|
||||||
|
ethAttached,
|
||||||
|
ethNeeded,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IncompleteTransformERC20Error extends RevertError {
|
||||||
|
constructor(outputToken?: string, outputTokenAmount?: Numberish, minOutputTokenAmount?: Numberish) {
|
||||||
|
super(
|
||||||
|
'IncompleteTransformERC20Error',
|
||||||
|
'IncompleteTransformERC20Error(address outputToken, uint256 outputTokenAmount, uint256 minOutputTokenAmount)',
|
||||||
|
{
|
||||||
|
outputToken,
|
||||||
|
outputTokenAmount,
|
||||||
|
minOutputTokenAmount,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NegativeTransformERC20OutputError extends RevertError {
|
||||||
|
constructor(outputToken?: string, outputTokenLostAmount?: Numberish) {
|
||||||
|
super(
|
||||||
|
'NegativeTransformERC20OutputError',
|
||||||
|
'NegativeTransformERC20OutputError(address outputToken, uint256 outputTokenLostAmount)',
|
||||||
|
{
|
||||||
|
outputToken,
|
||||||
|
outputTokenLostAmount,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UnauthorizedTransformerError extends RevertError {
|
||||||
|
constructor(transformer?: string, rlpNonce?: string) {
|
||||||
|
super('UnauthorizedTransformerError', 'UnauthorizedTransformerError(address transformer, bytes rlpNonce)', {
|
||||||
|
transformer,
|
||||||
|
rlpNonce,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InvalidRLPNonceError extends RevertError {
|
||||||
|
constructor(rlpNonce?: string) {
|
||||||
|
super('InvalidRLPNonceError', 'InvalidRLPNonceError(bytes rlpNonce)', { rlpNonce });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IncompleteFillSellQuoteError extends RevertError {
|
||||||
|
constructor(sellToken?: string, soldAmount?: Numberish, sellAmount?: Numberish) {
|
||||||
|
super(
|
||||||
|
'IncompleteFillSellQuoteError',
|
||||||
|
'IncompleteFillSellQuoteError(address sellToken, address[] soldAmount, uint256[] sellAmount)',
|
||||||
|
{
|
||||||
|
sellToken,
|
||||||
|
soldAmount,
|
||||||
|
sellAmount,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IncompleteFillBuyQuoteError extends RevertError {
|
||||||
|
constructor(buyToken?: string, boughtAmount?: Numberish, buyAmount?: Numberish) {
|
||||||
|
super(
|
||||||
|
'IncompleteFillBuyQuoteError',
|
||||||
|
'IncompleteFillBuyQuoteError(address buyToken, address[] boughtAmount, uint256[] buyAmount)',
|
||||||
|
{
|
||||||
|
buyToken,
|
||||||
|
boughtAmount,
|
||||||
|
buyAmount,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InsufficientTakerTokenError extends RevertError {
|
||||||
|
constructor(tokenBalance?: Numberish, tokensNeeded?: Numberish) {
|
||||||
|
super(
|
||||||
|
'InsufficientTakerTokenError',
|
||||||
|
'InsufficientTakerTokenError(uint256 tokenBalance, uint256 tokensNeeded)',
|
||||||
|
{
|
||||||
|
tokenBalance,
|
||||||
|
tokensNeeded,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InsufficientProtocolFeeError extends RevertError {
|
||||||
|
constructor(ethBalance?: Numberish, ethNeeded?: Numberish) {
|
||||||
|
super('InsufficientProtocolFeeError', 'InsufficientProtocolFeeError(uint256 ethBalance, uint256 ethNeeded)', {
|
||||||
|
ethBalance,
|
||||||
|
ethNeeded,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InvalidERC20AssetDataError extends RevertError {
|
||||||
|
constructor(assetData?: string) {
|
||||||
|
super('InvalidERC20AssetDataError', 'InvalidERC20AssetDataError(bytes assetData)', {
|
||||||
|
assetData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WrongNumberOfTokensReceivedError extends RevertError {
|
||||||
|
constructor(actual?: Numberish, expected?: Numberish) {
|
||||||
|
super(
|
||||||
|
'WrongNumberOfTokensReceivedError',
|
||||||
|
'WrongNumberOfTokensReceivedError(uint256 actual, uint256 expected)',
|
||||||
|
{
|
||||||
|
actual,
|
||||||
|
expected,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InvalidTokenReceivedError extends RevertError {
|
||||||
|
constructor(token?: string) {
|
||||||
|
super('InvalidTokenReceivedError', 'InvalidTokenReceivedError(address token)', {
|
||||||
|
token,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const types = [
|
||||||
|
InsufficientEthAttachedError,
|
||||||
|
IncompleteTransformERC20Error,
|
||||||
|
NegativeTransformERC20OutputError,
|
||||||
|
UnauthorizedTransformerError,
|
||||||
|
InvalidRLPNonceError,
|
||||||
|
IncompleteFillSellQuoteError,
|
||||||
|
IncompleteFillBuyQuoteError,
|
||||||
|
InsufficientTakerTokenError,
|
||||||
|
InsufficientProtocolFeeError,
|
||||||
|
InvalidERC20AssetDataError,
|
||||||
|
WrongNumberOfTokensReceivedError,
|
||||||
|
InvalidTokenReceivedError,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Register the types we've defined.
|
||||||
|
for (const type of types) {
|
||||||
|
RevertError.registerType(type);
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import { RevertError } from '../../revert_error';
|
||||||
|
import { Numberish } from '../../types';
|
||||||
|
|
||||||
|
// tslint:disable:max-classes-per-file
|
||||||
|
export class WalletExecuteCallFailedError extends RevertError {
|
||||||
|
constructor(wallet?: string, callTarget?: string, callData?: string, callValue?: Numberish, errorData?: string) {
|
||||||
|
super(
|
||||||
|
'WalletExecuteCallFailedError',
|
||||||
|
'WalletExecuteCallFailedError(address wallet, address callTarget, bytes callData, uint256 callValue, bytes errorData)',
|
||||||
|
{
|
||||||
|
wallet,
|
||||||
|
callTarget,
|
||||||
|
callData,
|
||||||
|
callValue,
|
||||||
|
errorData,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WalletExecuteDelegateCallFailedError extends RevertError {
|
||||||
|
constructor(wallet?: string, callTarget?: string, callData?: string, errorData?: string) {
|
||||||
|
super(
|
||||||
|
'WalletExecuteDelegateCallFailedError',
|
||||||
|
'WalletExecuteDelegateCallFailedError(address wallet, address callTarget, bytes callData, bytes errorData)',
|
||||||
|
{
|
||||||
|
wallet,
|
||||||
|
callTarget,
|
||||||
|
callData,
|
||||||
|
errorData,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const types = [WalletExecuteCallFailedError, WalletExecuteDelegateCallFailedError];
|
||||||
|
|
||||||
|
// Register the types we've defined.
|
||||||
|
for (const type of types) {
|
||||||
|
RevertError.registerType(type);
|
||||||
|
}
|
@ -1,4 +1,17 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "7.1.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add `getAccountNonce()` to `Web3Wrapper`",
|
||||||
|
"pr": 2545
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Update ganache-core",
|
||||||
|
"pr": 2545
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1582623685,
|
"timestamp": 1582623685,
|
||||||
"version": "7.0.7",
|
"version": "7.0.7",
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
"chai-as-promised": "^7.1.0",
|
"chai-as-promised": "^7.1.0",
|
||||||
"chai-bignumber": "^3.0.0",
|
"chai-bignumber": "^3.0.0",
|
||||||
"dirty-chai": "^2.0.1",
|
"dirty-chai": "^2.0.1",
|
||||||
"ganache-core": "^2.9.0-istanbul.0",
|
"ganache-core": "^2.10.2",
|
||||||
"make-promises-safe": "^1.1.0",
|
"make-promises-safe": "^1.1.0",
|
||||||
"mocha": "^6.2.0",
|
"mocha": "^6.2.0",
|
||||||
"npm-run-all": "^4.1.2",
|
"npm-run-all": "^4.1.2",
|
||||||
|
@ -360,6 +360,27 @@ export class Web3Wrapper {
|
|||||||
const blockNumber = utils.convertHexToNumberOrNull(blockNumberHex);
|
const blockNumber = utils.convertHexToNumberOrNull(blockNumberHex);
|
||||||
return blockNumber as number;
|
return blockNumber as number;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Fetches the nonce for an account (transaction count for EOAs).
|
||||||
|
* @param address Address of account.
|
||||||
|
* @param defaultBlock Block height at which to make the call. Defaults to `latest`
|
||||||
|
* @returns Account nonce.
|
||||||
|
*/
|
||||||
|
public async getAccountNonceAsync(address: string, defaultBlock?: BlockParam): Promise<number> {
|
||||||
|
assert.isETHAddressHex('address', address);
|
||||||
|
if (defaultBlock !== undefined) {
|
||||||
|
Web3Wrapper._assertBlockParam(defaultBlock);
|
||||||
|
}
|
||||||
|
const marshalledDefaultBlock = marshaller.marshalBlockParam(defaultBlock);
|
||||||
|
const encodedAddress = marshaller.marshalAddress(address);
|
||||||
|
const nonceHex = await this.sendRawPayloadAsync<string>({
|
||||||
|
method: 'eth_getTransactionCount',
|
||||||
|
params: [encodedAddress, marshalledDefaultBlock],
|
||||||
|
});
|
||||||
|
assert.isHexString('nonce', nonceHex);
|
||||||
|
// tslint:disable-next-line:custom-no-magic-numbers
|
||||||
|
return parseInt(nonceHex.substr(2), 16);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Fetch a specific Ethereum block without transaction data
|
* Fetch a specific Ethereum block without transaction data
|
||||||
* @param blockParam The block you wish to fetch (blockHash, blockNumber or blockLiteral)
|
* @param blockParam The block you wish to fetch (blockHash, blockNumber or blockLiteral)
|
||||||
|
@ -35,8 +35,7 @@ describe('Web3Wrapper tests', () => {
|
|||||||
describe('#getNodeVersionAsync', () => {
|
describe('#getNodeVersionAsync', () => {
|
||||||
it('gets the node version', async () => {
|
it('gets the node version', async () => {
|
||||||
const nodeVersion = await web3Wrapper.getNodeVersionAsync();
|
const nodeVersion = await web3Wrapper.getNodeVersionAsync();
|
||||||
const NODE_VERSION = 'EthereumJS TestRPC/v2.9.0-istanbul.0/ethereum-js';
|
expect(nodeVersion).to.be.match(/EthereumJS TestRPC\/.+\/ethereum-js$/);
|
||||||
expect(nodeVersion).to.be.equal(NODE_VERSION);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getNetworkIdAsync', () => {
|
describe('#getNetworkIdAsync', () => {
|
||||||
|
486
yarn.lock
486
yarn.lock
@ -1971,6 +1971,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.3.0"
|
"@babel/types" "^7.3.0"
|
||||||
|
|
||||||
|
"@types/bignumber.js@^5.0.0":
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz#d9f1a378509f3010a3255e9cc822ad0eeb4ab969"
|
||||||
|
integrity sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==
|
||||||
|
dependencies:
|
||||||
|
bignumber.js "*"
|
||||||
|
|
||||||
"@types/bip39@^2.4.0":
|
"@types/bip39@^2.4.0":
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/bip39/-/bip39-2.4.0.tgz#eee31a14abc8ebbb41a1ff14575c447b18346cbc"
|
resolved "https://registry.yarnpkg.com/@types/bip39/-/bip39-2.4.0.tgz#eee31a14abc8ebbb41a1ff14575c447b18346cbc"
|
||||||
@ -2285,6 +2292,25 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/yargs-parser" "*"
|
"@types/yargs-parser" "*"
|
||||||
|
|
||||||
|
"@web3-js/scrypt-shim@^0.1.0":
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz#0bf7529ab6788311d3e07586f7d89107c3bea2cc"
|
||||||
|
integrity sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==
|
||||||
|
dependencies:
|
||||||
|
scryptsy "^2.1.0"
|
||||||
|
semver "^6.3.0"
|
||||||
|
|
||||||
|
"@web3-js/websocket@^1.0.29":
|
||||||
|
version "1.0.30"
|
||||||
|
resolved "https://registry.yarnpkg.com/@web3-js/websocket/-/websocket-1.0.30.tgz#9ea15b7b582cf3bf3e8bc1f4d3d54c0731a87f87"
|
||||||
|
integrity sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==
|
||||||
|
dependencies:
|
||||||
|
debug "^2.2.0"
|
||||||
|
es5-ext "^0.10.50"
|
||||||
|
nan "^2.14.0"
|
||||||
|
typedarray-to-buffer "^3.1.5"
|
||||||
|
yaeti "^0.0.6"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.7.8":
|
"@webassemblyjs/ast@1.7.8":
|
||||||
version "1.7.8"
|
version "1.7.8"
|
||||||
resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.8.tgz#f31f480debeef957f01b623f27eabc695fa4fe8f"
|
resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.8.tgz#f31f480debeef957f01b623f27eabc695fa4fe8f"
|
||||||
@ -3802,6 +3828,10 @@ big.js@^5.2.2:
|
|||||||
version "5.2.2"
|
version "5.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||||
|
|
||||||
|
bignumber.js@*, bignumber.js@~9.0.0:
|
||||||
|
version "9.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075"
|
||||||
|
|
||||||
bignumber.js@7.2.1:
|
bignumber.js@7.2.1:
|
||||||
version "7.2.1"
|
version "7.2.1"
|
||||||
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
||||||
@ -3814,10 +3844,6 @@ bignumber.js@~8.0.2:
|
|||||||
version "8.0.2"
|
version "8.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.2.tgz#d8c4e1874359573b1ef03011a2d861214aeef137"
|
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.2.tgz#d8c4e1874359573b1ef03011a2d861214aeef137"
|
||||||
|
|
||||||
bignumber.js@~9.0.0:
|
|
||||||
version "9.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075"
|
|
||||||
|
|
||||||
binary-extensions@^1.0.0:
|
binary-extensions@^1.0.0:
|
||||||
version "1.11.0"
|
version "1.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
|
||||||
@ -6691,6 +6717,13 @@ ethashjs@~0.0.7:
|
|||||||
ethereumjs-util "^4.0.1"
|
ethereumjs-util "^4.0.1"
|
||||||
miller-rabin "^4.0.0"
|
miller-rabin "^4.0.0"
|
||||||
|
|
||||||
|
ethereum-bloom-filters@^1.0.6:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz#b7b80735e385dbb7f944ce6b4533e24511306060"
|
||||||
|
integrity sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==
|
||||||
|
dependencies:
|
||||||
|
js-sha3 "^0.8.0"
|
||||||
|
|
||||||
ethereum-common@0.2.0:
|
ethereum-common@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca"
|
resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca"
|
||||||
@ -6749,13 +6782,14 @@ ethereumjs-account@^2.0.3:
|
|||||||
ethereumjs-util "^4.0.1"
|
ethereumjs-util "^4.0.1"
|
||||||
rlp "^2.0.0"
|
rlp "^2.0.0"
|
||||||
|
|
||||||
ethereumjs-block@2.2.0, ethereumjs-block@~2.2.0:
|
ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.2:
|
||||||
version "2.2.0"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.0.tgz#8c6c3ab4a5eff0a16d9785fbeedbe643f4dbcbef"
|
resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965"
|
||||||
|
integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==
|
||||||
dependencies:
|
dependencies:
|
||||||
async "^2.0.1"
|
async "^2.0.1"
|
||||||
ethereumjs-common "^1.1.0"
|
ethereumjs-common "^1.5.0"
|
||||||
ethereumjs-tx "^1.2.2"
|
ethereumjs-tx "^2.1.1"
|
||||||
ethereumjs-util "^5.0.0"
|
ethereumjs-util "^5.0.0"
|
||||||
merkle-patricia-tree "^2.1.2"
|
merkle-patricia-tree "^2.1.2"
|
||||||
|
|
||||||
@ -6769,6 +6803,16 @@ ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0, ether
|
|||||||
ethereumjs-util "^5.0.0"
|
ethereumjs-util "^5.0.0"
|
||||||
merkle-patricia-tree "^2.1.2"
|
merkle-patricia-tree "^2.1.2"
|
||||||
|
|
||||||
|
ethereumjs-block@~2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.0.tgz#8c6c3ab4a5eff0a16d9785fbeedbe643f4dbcbef"
|
||||||
|
dependencies:
|
||||||
|
async "^2.0.1"
|
||||||
|
ethereumjs-common "^1.1.0"
|
||||||
|
ethereumjs-tx "^1.2.2"
|
||||||
|
ethereumjs-util "^5.0.0"
|
||||||
|
merkle-patricia-tree "^2.1.2"
|
||||||
|
|
||||||
ethereumjs-blockchain@^4.0.1:
|
ethereumjs-blockchain@^4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.1.tgz#db113dfed4fcc5197d223391f10adbc5a1b3536b"
|
resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.1.tgz#db113dfed4fcc5197d223391f10adbc5a1b3536b"
|
||||||
@ -6784,6 +6828,22 @@ ethereumjs-blockchain@^4.0.1:
|
|||||||
rlp "^2.2.2"
|
rlp "^2.2.2"
|
||||||
semaphore "^1.1.0"
|
semaphore "^1.1.0"
|
||||||
|
|
||||||
|
ethereumjs-blockchain@^4.0.3:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.3.tgz#e013034633a30ad2006728e8e2b21956b267b773"
|
||||||
|
integrity sha512-0nJWbyA+Gu0ZKZr/cywMtB/77aS/4lOVsIKbgUN2sFQYscXO5rPbUfrEe7G2Zhjp86/a0VqLllemDSTHvx3vZA==
|
||||||
|
dependencies:
|
||||||
|
async "^2.6.1"
|
||||||
|
ethashjs "~0.0.7"
|
||||||
|
ethereumjs-block "~2.2.2"
|
||||||
|
ethereumjs-common "^1.5.0"
|
||||||
|
ethereumjs-util "~6.1.0"
|
||||||
|
flow-stoplight "^1.0.0"
|
||||||
|
level-mem "^3.0.1"
|
||||||
|
lru-cache "^5.1.1"
|
||||||
|
rlp "^2.2.2"
|
||||||
|
semaphore "^1.1.0"
|
||||||
|
|
||||||
ethereumjs-blockstream@^7.0.0:
|
ethereumjs-blockstream@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-blockstream/-/ethereumjs-blockstream-7.0.0.tgz#b8d7b6257dd1100bc6ddb36d6bef58c2490f9999"
|
resolved "https://registry.yarnpkg.com/ethereumjs-blockstream/-/ethereumjs-blockstream-7.0.0.tgz#b8d7b6257dd1100bc6ddb36d6bef58c2490f9999"
|
||||||
@ -6792,6 +6852,10 @@ ethereumjs-blockstream@^7.0.0:
|
|||||||
source-map-support "0.5.6"
|
source-map-support "0.5.6"
|
||||||
uuid "3.2.1"
|
uuid "3.2.1"
|
||||||
|
|
||||||
|
ethereumjs-common@1.5.0, ethereumjs-common@^1.3.1, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0:
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd"
|
||||||
|
|
||||||
ethereumjs-common@^1.1.0:
|
ethereumjs-common@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.1.0.tgz#5ec9086c314d619d8f05e79a0525829fcb0e93cb"
|
resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.1.0.tgz#5ec9086c314d619d8f05e79a0525829fcb0e93cb"
|
||||||
@ -6800,16 +6864,13 @@ ethereumjs-common@^1.3.0:
|
|||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.3.1.tgz#a5cffac41beb7ad393283b2e5aa71fadf8a9cc73"
|
resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.3.1.tgz#a5cffac41beb7ad393283b2e5aa71fadf8a9cc73"
|
||||||
|
|
||||||
ethereumjs-common@^1.3.1, ethereumjs-common@^1.3.2:
|
ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.2:
|
||||||
version "1.5.0"
|
version "2.1.2"
|
||||||
resolved "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd"
|
resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed"
|
||||||
|
integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==
|
||||||
ethereumjs-tx@1.3.7:
|
|
||||||
version "1.3.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a"
|
|
||||||
dependencies:
|
dependencies:
|
||||||
ethereum-common "^0.0.18"
|
ethereumjs-common "^1.5.0"
|
||||||
ethereumjs-util "^5.0.0"
|
ethereumjs-util "^6.0.0"
|
||||||
|
|
||||||
ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.5:
|
ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.5:
|
||||||
version "1.3.5"
|
version "1.3.5"
|
||||||
@ -6844,6 +6905,18 @@ ethereumjs-util@6.1.0, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumj
|
|||||||
safe-buffer "^5.1.1"
|
safe-buffer "^5.1.1"
|
||||||
secp256k1 "^3.0.1"
|
secp256k1 "^3.0.1"
|
||||||
|
|
||||||
|
ethereumjs-util@6.2.0, ethereumjs-util@^6.2.0:
|
||||||
|
version "6.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960"
|
||||||
|
dependencies:
|
||||||
|
"@types/bn.js" "^4.11.3"
|
||||||
|
bn.js "^4.11.0"
|
||||||
|
create-hash "^1.1.2"
|
||||||
|
ethjs-util "0.1.6"
|
||||||
|
keccak "^2.0.0"
|
||||||
|
rlp "^2.2.3"
|
||||||
|
secp256k1 "^3.0.1"
|
||||||
|
|
||||||
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0:
|
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
|
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
|
||||||
@ -6866,31 +6939,20 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum
|
|||||||
safe-buffer "^5.1.1"
|
safe-buffer "^5.1.1"
|
||||||
secp256k1 "^3.0.1"
|
secp256k1 "^3.0.1"
|
||||||
|
|
||||||
ethereumjs-util@^6.2.0:
|
ethereumjs-vm@4.1.3:
|
||||||
version "6.2.0"
|
version "4.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960"
|
resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.1.3.tgz#dc8eb45f47d775da9f0b2437d5e20896fdf66f37"
|
||||||
dependencies:
|
integrity sha512-RTrD0y7My4O6Qr1P2ZIsMfD6RzL6kU/RhBZ0a5XrPzAeR61crBS7or66ohDrvxDI/rDBxMi+6SnsELih6fzalw==
|
||||||
"@types/bn.js" "^4.11.3"
|
|
||||||
bn.js "^4.11.0"
|
|
||||||
create-hash "^1.1.2"
|
|
||||||
ethjs-util "0.1.6"
|
|
||||||
keccak "^2.0.0"
|
|
||||||
rlp "^2.2.3"
|
|
||||||
secp256k1 "^3.0.1"
|
|
||||||
|
|
||||||
ethereumjs-vm@4.1.0:
|
|
||||||
version "4.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.1.0.tgz#359ed3592636390a5b2909a28d955c908830daa5"
|
|
||||||
dependencies:
|
dependencies:
|
||||||
async "^2.1.2"
|
async "^2.1.2"
|
||||||
async-eventemitter "^0.2.2"
|
async-eventemitter "^0.2.2"
|
||||||
core-js-pure "^3.0.1"
|
core-js-pure "^3.0.1"
|
||||||
ethereumjs-account "^3.0.0"
|
ethereumjs-account "^3.0.0"
|
||||||
ethereumjs-block "~2.2.0"
|
ethereumjs-block "^2.2.2"
|
||||||
ethereumjs-blockchain "^4.0.1"
|
ethereumjs-blockchain "^4.0.3"
|
||||||
ethereumjs-common "^1.3.2"
|
ethereumjs-common "^1.5.0"
|
||||||
ethereumjs-tx "^2.1.1"
|
ethereumjs-tx "^2.1.2"
|
||||||
ethereumjs-util "^6.1.0"
|
ethereumjs-util "^6.2.0"
|
||||||
fake-merkle-patricia-tree "^1.0.1"
|
fake-merkle-patricia-tree "^1.0.1"
|
||||||
functional-red-black-tree "^1.0.1"
|
functional-red-black-tree "^1.0.1"
|
||||||
merkle-patricia-tree "^2.3.2"
|
merkle-patricia-tree "^2.3.2"
|
||||||
@ -7917,9 +7979,10 @@ ganache-cli@6.8.0-istanbul.0:
|
|||||||
source-map-support "0.5.12"
|
source-map-support "0.5.12"
|
||||||
yargs "13.2.4"
|
yargs "13.2.4"
|
||||||
|
|
||||||
ganache-core@^2.9.0-istanbul.0:
|
ganache-core@^2.10.2:
|
||||||
version "2.9.0-istanbul.0"
|
version "2.10.2"
|
||||||
resolved "https://registry.npmjs.org/ganache-core/-/ganache-core-2.9.0-istanbul.0.tgz#bc336c770775a2b9fb06f5cae827088ecc194283"
|
resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.10.2.tgz#17c171c6c0195b6734a0dd741a9d2afd4f74e292"
|
||||||
|
integrity sha512-4XEO0VsqQ1+OW7Za5fQs9/Kk7o8M0T1sRfFSF8h9NeJ2ABaqMO5waqxf567ZMcSkRKaTjUucBSz83xNfZv1HDg==
|
||||||
dependencies:
|
dependencies:
|
||||||
abstract-leveldown "3.0.0"
|
abstract-leveldown "3.0.0"
|
||||||
async "2.6.2"
|
async "2.6.2"
|
||||||
@ -7931,10 +7994,11 @@ ganache-core@^2.9.0-istanbul.0:
|
|||||||
eth-sig-util "2.3.0"
|
eth-sig-util "2.3.0"
|
||||||
ethereumjs-abi "0.6.7"
|
ethereumjs-abi "0.6.7"
|
||||||
ethereumjs-account "3.0.0"
|
ethereumjs-account "3.0.0"
|
||||||
ethereumjs-block "2.2.0"
|
ethereumjs-block "2.2.2"
|
||||||
ethereumjs-tx "1.3.7"
|
ethereumjs-common "1.5.0"
|
||||||
ethereumjs-util "6.1.0"
|
ethereumjs-tx "2.1.2"
|
||||||
ethereumjs-vm "4.1.0"
|
ethereumjs-util "6.2.0"
|
||||||
|
ethereumjs-vm "4.1.3"
|
||||||
heap "0.2.6"
|
heap "0.2.6"
|
||||||
level-sublevel "6.6.4"
|
level-sublevel "6.6.4"
|
||||||
levelup "3.1.1"
|
levelup "3.1.1"
|
||||||
@ -7947,7 +8011,7 @@ ganache-core@^2.9.0-istanbul.0:
|
|||||||
websocket "1.0.29"
|
websocket "1.0.29"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
ethereumjs-wallet "0.6.3"
|
ethereumjs-wallet "0.6.3"
|
||||||
web3 "1.2.1"
|
web3 "1.2.4"
|
||||||
|
|
||||||
gauge@~1.2.5:
|
gauge@~1.2.5:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
@ -10383,6 +10447,11 @@ js-sha3@^0.7.0:
|
|||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a"
|
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a"
|
||||||
|
|
||||||
|
js-sha3@^0.8.0:
|
||||||
|
version "0.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
|
||||||
|
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
|
||||||
|
|
||||||
js-tokens@^3.0.0, js-tokens@^3.0.2:
|
js-tokens@^3.0.0, js-tokens@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||||
@ -14757,16 +14826,17 @@ scrypt@^6.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
nan "^2.0.8"
|
nan "^2.0.8"
|
||||||
|
|
||||||
scryptsy@2.1.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
|
|
||||||
|
|
||||||
scryptsy@^1.2.1:
|
scryptsy@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163"
|
resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163"
|
||||||
dependencies:
|
dependencies:
|
||||||
pbkdf2 "^3.0.3"
|
pbkdf2 "^3.0.3"
|
||||||
|
|
||||||
|
scryptsy@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
|
||||||
|
integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==
|
||||||
|
|
||||||
secp256k1@^3.0.1:
|
secp256k1@^3.0.1:
|
||||||
version "3.5.0"
|
version "3.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.0.tgz#677d3b8a8e04e1a5fa381a1ae437c54207b738d0"
|
resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.0.tgz#677d3b8a8e04e1a5fa381a1ae437c54207b738d0"
|
||||||
@ -14847,10 +14917,6 @@ semver-sort@0.0.4:
|
|||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
||||||
|
|
||||||
semver@6.2.0:
|
|
||||||
version "6.2.0"
|
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db"
|
|
||||||
|
|
||||||
semver@^5.5.1:
|
semver@^5.5.1:
|
||||||
version "5.6.0"
|
version "5.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||||
@ -14859,7 +14925,7 @@ semver@^5.6.0, semver@^5.7.0:
|
|||||||
version "5.7.0"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
|
||||||
|
|
||||||
semver@^6.0.0, semver@^6.2.0:
|
semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
|
||||||
version "6.3.0"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
|
|
||||||
@ -17041,10 +17107,12 @@ wcwidth@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defaults "^1.0.3"
|
defaults "^1.0.3"
|
||||||
|
|
||||||
web3-bzz@1.2.1:
|
web3-bzz@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.1.tgz#c3bd1e8f0c02a13cd6d4e3c3e9e1713f144f6f0d"
|
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.4.tgz#a4adb7a8cba3d260de649bdb1f14ed359bfb3821"
|
||||||
|
integrity sha512-MqhAo/+0iQSMBtt3/QI1rU83uvF08sYq8r25+OUZ+4VtihnYsmkkca+rdU0QbRyrXY2/yGIpI46PFdh0khD53A==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@types/node" "^10.12.18"
|
||||||
got "9.6.0"
|
got "9.6.0"
|
||||||
swarm-js "0.1.39"
|
swarm-js "0.1.39"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
@ -17057,13 +17125,14 @@ web3-core-helpers@1.0.0-beta.34:
|
|||||||
web3-eth-iban "1.0.0-beta.34"
|
web3-eth-iban "1.0.0-beta.34"
|
||||||
web3-utils "1.0.0-beta.34"
|
web3-utils "1.0.0-beta.34"
|
||||||
|
|
||||||
web3-core-helpers@1.2.1:
|
web3-core-helpers@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.1.tgz#f5f32d71c60a4a3bd14786118e633ce7ca6d5d0d"
|
resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.4.tgz#ffd425861f4d66b3f38df032afdb39ea0971fc0f"
|
||||||
|
integrity sha512-U7wbsK8IbZvF3B7S+QMSNP0tni/6VipnJkB0tZVEpHEIV2WWeBHYmZDnULWcsS/x/jn9yKhJlXIxWGsEAMkjiw==
|
||||||
dependencies:
|
dependencies:
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-eth-iban "1.2.1"
|
web3-eth-iban "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-core-helpers@2.0.0-alpha:
|
web3-core-helpers@2.0.0-alpha:
|
||||||
version "2.0.0-alpha"
|
version "2.0.0-alpha"
|
||||||
@ -17075,15 +17144,16 @@ web3-core-helpers@2.0.0-alpha:
|
|||||||
web3-eth-iban "2.0.0-alpha"
|
web3-eth-iban "2.0.0-alpha"
|
||||||
web3-utils "2.0.0-alpha"
|
web3-utils "2.0.0-alpha"
|
||||||
|
|
||||||
web3-core-method@1.2.1:
|
web3-core-method@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.1.tgz#9df1bafa2cd8be9d9937e01c6a47fc768d15d90a"
|
resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.4.tgz#a0fbc50b8ff5fd214021435cc2c6d1e115807aed"
|
||||||
|
integrity sha512-8p9kpL7di2qOVPWgcM08kb+yKom0rxRCMv6m/K+H+yLSxev9TgMbCgMSbPWAHlyiF3SJHw7APFKahK5Z+8XT5A==
|
||||||
dependencies:
|
dependencies:
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-core-promievent "1.2.1"
|
web3-core-promievent "1.2.4"
|
||||||
web3-core-subscriptions "1.2.1"
|
web3-core-subscriptions "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-core-method@2.0.0-alpha:
|
web3-core-method@2.0.0-alpha:
|
||||||
version "2.0.0-alpha"
|
version "2.0.0-alpha"
|
||||||
@ -17098,30 +17168,33 @@ web3-core-method@2.0.0-alpha:
|
|||||||
web3-core-subscriptions "2.0.0-alpha"
|
web3-core-subscriptions "2.0.0-alpha"
|
||||||
web3-utils "2.0.0-alpha"
|
web3-utils "2.0.0-alpha"
|
||||||
|
|
||||||
web3-core-promievent@1.2.1:
|
web3-core-promievent@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz#003e8a3eb82fb27b6164a6d5b9cad04acf733838"
|
resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.4.tgz#75e5c0f2940028722cdd21ba503ebd65272df6cb"
|
||||||
|
integrity sha512-gEUlm27DewUsfUgC3T8AxkKi8Ecx+e+ZCaunB7X4Qk3i9F4C+5PSMGguolrShZ7Zb6717k79Y86f3A00O0VAZw==
|
||||||
dependencies:
|
dependencies:
|
||||||
any-promise "1.3.0"
|
any-promise "1.3.0"
|
||||||
eventemitter3 "3.1.2"
|
eventemitter3 "3.1.2"
|
||||||
|
|
||||||
web3-core-requestmanager@1.2.1:
|
web3-core-requestmanager@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz#fa2e2206c3d738db38db7c8fe9c107006f5c6e3d"
|
resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.4.tgz#0a7020a23fb91c6913c611dfd3d8c398d1e4b4a8"
|
||||||
|
integrity sha512-eZJDjyNTDtmSmzd3S488nR/SMJtNnn/GuwxnMh3AzYCqG3ZMfOylqTad2eYJPvc2PM5/Gj1wAMQcRpwOjjLuPg==
|
||||||
dependencies:
|
dependencies:
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-providers-http "1.2.1"
|
web3-providers-http "1.2.4"
|
||||||
web3-providers-ipc "1.2.1"
|
web3-providers-ipc "1.2.4"
|
||||||
web3-providers-ws "1.2.1"
|
web3-providers-ws "1.2.4"
|
||||||
|
|
||||||
web3-core-subscriptions@1.2.1:
|
web3-core-subscriptions@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz#8c2368a839d4eec1c01a4b5650bbeb82d0e4a099"
|
resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.4.tgz#0dc095b5cfd82baa527a39796e3515a846b21b99"
|
||||||
|
integrity sha512-3D607J2M8ymY9V+/WZq4MLlBulwCkwEjjC2U+cXqgVO1rCyVqbxZNCmHyNYHjDDCxSEbks9Ju5xqJxDSxnyXEw==
|
||||||
dependencies:
|
dependencies:
|
||||||
eventemitter3 "3.1.2"
|
eventemitter3 "3.1.2"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
|
|
||||||
web3-core-subscriptions@2.0.0-alpha:
|
web3-core-subscriptions@2.0.0-alpha:
|
||||||
version "2.0.0-alpha"
|
version "2.0.0-alpha"
|
||||||
@ -17131,14 +17204,18 @@ web3-core-subscriptions@2.0.0-alpha:
|
|||||||
eventemitter3 "^3.1.0"
|
eventemitter3 "^3.1.0"
|
||||||
lodash "^4.17.11"
|
lodash "^4.17.11"
|
||||||
|
|
||||||
web3-core@1.2.1:
|
web3-core@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-core/-/web3-core-1.2.1.tgz#7278b58fb6495065e73a77efbbce781a7fddf1a9"
|
resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.4.tgz#2df13b978dcfc59c2abaa887d27f88f21ad9a9d6"
|
||||||
|
integrity sha512-CHc27sMuET2cs1IKrkz7xzmTdMfZpYswe7f0HcuyneTwS1yTlTnHyqjAaTy0ZygAb/x4iaVox+Gvr4oSAqSI+A==
|
||||||
dependencies:
|
dependencies:
|
||||||
web3-core-helpers "1.2.1"
|
"@types/bignumber.js" "^5.0.0"
|
||||||
web3-core-method "1.2.1"
|
"@types/bn.js" "^4.11.4"
|
||||||
web3-core-requestmanager "1.2.1"
|
"@types/node" "^12.6.1"
|
||||||
web3-utils "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
|
web3-core-method "1.2.4"
|
||||||
|
web3-core-requestmanager "1.2.4"
|
||||||
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-core@2.0.0-alpha:
|
web3-core@2.0.0-alpha:
|
||||||
version "2.0.0-alpha"
|
version "2.0.0-alpha"
|
||||||
@ -17152,13 +17229,14 @@ web3-core@2.0.0-alpha:
|
|||||||
web3-providers "2.0.0-alpha"
|
web3-providers "2.0.0-alpha"
|
||||||
web3-utils "2.0.0-alpha"
|
web3-utils "2.0.0-alpha"
|
||||||
|
|
||||||
web3-eth-abi@1.2.1:
|
web3-eth-abi@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz#9b915b1c9ebf82f70cca631147035d5419064689"
|
resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.4.tgz#5b73e5ef70b03999227066d5d1310b168845e2b8"
|
||||||
|
integrity sha512-8eLIY4xZKoU3DSVu1pORluAw9Ru0/v4CGdw5so31nn+7fR8zgHMgwbFe0aOqWQ5VU42PzMMXeIJwt4AEi2buFg==
|
||||||
dependencies:
|
dependencies:
|
||||||
ethers "4.0.0-beta.3"
|
ethers "4.0.0-beta.3"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-eth-abi@^1.0.0-beta.24:
|
web3-eth-abi@^1.0.0-beta.24:
|
||||||
version "1.0.0-beta.34"
|
version "1.0.0-beta.34"
|
||||||
@ -17169,47 +17247,52 @@ web3-eth-abi@^1.0.0-beta.24:
|
|||||||
web3-core-helpers "1.0.0-beta.34"
|
web3-core-helpers "1.0.0-beta.34"
|
||||||
web3-utils "1.0.0-beta.34"
|
web3-utils "1.0.0-beta.34"
|
||||||
|
|
||||||
web3-eth-accounts@1.2.1:
|
web3-eth-accounts@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz#2741a8ef337a7219d57959ac8bd118b9d68d63cf"
|
resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.4.tgz#ada6edc49542354328a85cafab067acd7f88c288"
|
||||||
|
integrity sha512-04LzT/UtWmRFmi4hHRewP5Zz43fWhuHiK5XimP86sUQodk/ByOkXQ3RoXyGXFMNoRxdcAeRNxSfA2DpIBc9xUw==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@web3-js/scrypt-shim" "^0.1.0"
|
||||||
any-promise "1.3.0"
|
any-promise "1.3.0"
|
||||||
crypto-browserify "3.12.0"
|
crypto-browserify "3.12.0"
|
||||||
eth-lib "0.2.7"
|
eth-lib "0.2.7"
|
||||||
scryptsy "2.1.0"
|
ethereumjs-common "^1.3.2"
|
||||||
semver "6.2.0"
|
ethereumjs-tx "^2.1.1"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
uuid "3.3.2"
|
uuid "3.3.2"
|
||||||
web3-core "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-core-method "1.2.1"
|
web3-core-method "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-eth-contract@1.2.1:
|
web3-eth-contract@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.1.tgz#3542424f3d341386fd9ff65e78060b85ac0ea8c4"
|
resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.4.tgz#68ef7cc633232779b0a2c506a810fbe903575886"
|
||||||
|
integrity sha512-b/9zC0qjVetEYnzRA1oZ8gF1OSSUkwSYi5LGr4GeckLkzXP7osEnp9lkO/AQcE4GpG+l+STnKPnASXJGZPgBRQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@types/bn.js" "^4.11.4"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-core-method "1.2.1"
|
web3-core-method "1.2.4"
|
||||||
web3-core-promievent "1.2.1"
|
web3-core-promievent "1.2.4"
|
||||||
web3-core-subscriptions "1.2.1"
|
web3-core-subscriptions "1.2.4"
|
||||||
web3-eth-abi "1.2.1"
|
web3-eth-abi "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-eth-ens@1.2.1:
|
web3-eth-ens@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.1.tgz#a0e52eee68c42a8b9865ceb04e5fb022c2d971d5"
|
resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.4.tgz#b95b3aa99fb1e35c802b9e02a44c3046a3fa065e"
|
||||||
|
integrity sha512-g8+JxnZlhdsCzCS38Zm6R/ngXhXzvc3h7bXlxgKU4coTzLLoMpgOAEz71GxyIJinWTFbLXk/WjNY0dazi9NwVw==
|
||||||
dependencies:
|
dependencies:
|
||||||
eth-ens-namehash "2.0.8"
|
eth-ens-namehash "2.0.8"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-core-promievent "1.2.1"
|
web3-core-promievent "1.2.4"
|
||||||
web3-eth-abi "1.2.1"
|
web3-eth-abi "1.2.4"
|
||||||
web3-eth-contract "1.2.1"
|
web3-eth-contract "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-eth-iban@1.0.0-beta.34:
|
web3-eth-iban@1.0.0-beta.34:
|
||||||
version "1.0.0-beta.34"
|
version "1.0.0-beta.34"
|
||||||
@ -17218,12 +17301,13 @@ web3-eth-iban@1.0.0-beta.34:
|
|||||||
bn.js "4.11.6"
|
bn.js "4.11.6"
|
||||||
web3-utils "1.0.0-beta.34"
|
web3-utils "1.0.0-beta.34"
|
||||||
|
|
||||||
web3-eth-iban@1.2.1:
|
web3-eth-iban@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.1.tgz#2c3801718946bea24e9296993a975c80b5acf880"
|
resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.4.tgz#8e0550fd3fd8e47a39357d87fe27dee9483ee476"
|
||||||
|
integrity sha512-D9HIyctru/FLRpXakRwmwdjb5bWU2O6UE/3AXvRm6DCOf2e+7Ve11qQrPtaubHfpdW3KWjDKvlxV9iaFv/oTMQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
bn.js "4.11.8"
|
bn.js "4.11.8"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-eth-iban@2.0.0-alpha:
|
web3-eth-iban@2.0.0-alpha:
|
||||||
version "2.0.0-alpha"
|
version "2.0.0-alpha"
|
||||||
@ -17233,41 +17317,45 @@ web3-eth-iban@2.0.0-alpha:
|
|||||||
bn.js "4.11.8"
|
bn.js "4.11.8"
|
||||||
web3-utils "2.0.0-alpha"
|
web3-utils "2.0.0-alpha"
|
||||||
|
|
||||||
web3-eth-personal@1.2.1:
|
web3-eth-personal@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz#244e9911b7b482dc17c02f23a061a627c6e47faf"
|
resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.4.tgz#3224cca6851c96347d9799b12c1b67b2a6eb232b"
|
||||||
|
integrity sha512-5Russ7ZECwHaZXcN3DLuLS7390Vzgrzepl4D87SD6Sn1DHsCZtvfdPIYwoTmKNp69LG3mORl7U23Ga5YxqkICw==
|
||||||
dependencies:
|
dependencies:
|
||||||
web3-core "1.2.1"
|
"@types/node" "^12.6.1"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-method "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-net "1.2.1"
|
web3-core-method "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-net "1.2.4"
|
||||||
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-eth@1.2.1:
|
web3-eth@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.1.tgz#b9989e2557c73a9e8ffdc107c6dafbe72c79c1b0"
|
resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.4.tgz#24c3b1f1ac79351bbfb808b2ab5c585fa57cdd00"
|
||||||
|
integrity sha512-+j+kbfmZsbc3+KJpvHM16j1xRFHe2jBAniMo1BHKc3lho6A8Sn9Buyut6odubguX2AxoRArCdIDCkT9hjUERpA==
|
||||||
dependencies:
|
dependencies:
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
web3-core-method "1.2.1"
|
web3-core-method "1.2.4"
|
||||||
web3-core-subscriptions "1.2.1"
|
web3-core-subscriptions "1.2.4"
|
||||||
web3-eth-abi "1.2.1"
|
web3-eth-abi "1.2.4"
|
||||||
web3-eth-accounts "1.2.1"
|
web3-eth-accounts "1.2.4"
|
||||||
web3-eth-contract "1.2.1"
|
web3-eth-contract "1.2.4"
|
||||||
web3-eth-ens "1.2.1"
|
web3-eth-ens "1.2.4"
|
||||||
web3-eth-iban "1.2.1"
|
web3-eth-iban "1.2.4"
|
||||||
web3-eth-personal "1.2.1"
|
web3-eth-personal "1.2.4"
|
||||||
web3-net "1.2.1"
|
web3-net "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-net@1.2.1:
|
web3-net@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-net/-/web3-net-1.2.1.tgz#edd249503315dd5ab4fa00220f6509d95bb7ab10"
|
resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.4.tgz#1d246406d3aaffbf39c030e4e98bce0ca5f25458"
|
||||||
|
integrity sha512-wKOsqhyXWPSYTGbp7ofVvni17yfRptpqoUdp3SC8RAhDmGkX6irsiT9pON79m6b3HUHfLoBilFQyt/fTUZOf7A==
|
||||||
dependencies:
|
dependencies:
|
||||||
web3-core "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-method "1.2.1"
|
web3-core-method "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
web3-provider-engine@14.0.6:
|
web3-provider-engine@14.0.6:
|
||||||
version "14.0.6"
|
version "14.0.6"
|
||||||
@ -17344,28 +17432,31 @@ web3-provider-engine@^13.3.2:
|
|||||||
xhr "^2.2.0"
|
xhr "^2.2.0"
|
||||||
xtend "^4.0.1"
|
xtend "^4.0.1"
|
||||||
|
|
||||||
web3-providers-http@1.2.1:
|
web3-providers-http@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.1.tgz#c93ea003a42e7b894556f7e19dd3540f947f5013"
|
resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.4.tgz#514fcad71ae77832c2c15574296282fbbc5f4a67"
|
||||||
|
integrity sha512-dzVCkRrR/cqlIrcrWNiPt9gyt0AZTE0J+MfAu9rR6CyIgtnm1wFUVVGaxYRxuTGQRO4Dlo49gtoGwaGcyxqiTw==
|
||||||
dependencies:
|
dependencies:
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
xhr2-cookies "1.1.0"
|
xhr2-cookies "1.1.0"
|
||||||
|
|
||||||
web3-providers-ipc@1.2.1:
|
web3-providers-ipc@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz#017bfc687a8fc5398df2241eb98f135e3edd672c"
|
resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.4.tgz#9d6659f8d44943fb369b739f48df09092be459bd"
|
||||||
|
integrity sha512-8J3Dguffin51gckTaNrO3oMBo7g+j0UNk6hXmdmQMMNEtrYqw4ctT6t06YOf9GgtOMjSAc1YEh3LPrvgIsR7og==
|
||||||
dependencies:
|
dependencies:
|
||||||
oboe "2.1.4"
|
oboe "2.1.4"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
|
|
||||||
web3-providers-ws@1.2.1:
|
web3-providers-ws@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz#2d941eaf3d5a8caa3214eff8dc16d96252b842cb"
|
resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.4.tgz#099ee271ee03f6ea4f5df9cfe969e83f4ce0e36f"
|
||||||
|
integrity sha512-F/vQpDzeK+++oeeNROl1IVTufFCwCR2hpWe5yRXN0ApLwHqXrMI7UwQNdJ9iyibcWjJf/ECbauEEQ8CHgE+MYQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@web3-js/websocket" "^1.0.29"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
web3-core-helpers "1.2.1"
|
web3-core-helpers "1.2.4"
|
||||||
websocket "github:web3-js/WebSocket-Node#polyfill/globalThis"
|
|
||||||
|
|
||||||
web3-providers@2.0.0-alpha:
|
web3-providers@2.0.0-alpha:
|
||||||
version "2.0.0-alpha"
|
version "2.0.0-alpha"
|
||||||
@ -17383,14 +17474,15 @@ web3-providers@2.0.0-alpha:
|
|||||||
websocket "^1.0.28"
|
websocket "^1.0.28"
|
||||||
xhr2-cookies "1.1.0"
|
xhr2-cookies "1.1.0"
|
||||||
|
|
||||||
web3-shh@1.2.1:
|
web3-shh@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.1.tgz#4460e3c1e07faf73ddec24ccd00da46f89152b0c"
|
resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.4.tgz#5c8ff5ab624a3b14f08af0d24d2b16c10e9f70dd"
|
||||||
|
integrity sha512-z+9SCw0dE+69Z/Hv8809XDbLj7lTfEv9Sgu8eKEIdGntZf4v7ewj5rzN5bZZSz8aCvfK7Y6ovz1PBAu4QzS4IQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
web3-core "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-core-method "1.2.1"
|
web3-core-method "1.2.4"
|
||||||
web3-core-subscriptions "1.2.1"
|
web3-core-subscriptions "1.2.4"
|
||||||
web3-net "1.2.1"
|
web3-net "1.2.4"
|
||||||
|
|
||||||
web3-typescript-typings@^0.10.2:
|
web3-typescript-typings@^0.10.2:
|
||||||
version "0.10.2"
|
version "0.10.2"
|
||||||
@ -17410,15 +17502,17 @@ web3-utils@1.0.0-beta.34:
|
|||||||
underscore "1.8.3"
|
underscore "1.8.3"
|
||||||
utf8 "2.1.1"
|
utf8 "2.1.1"
|
||||||
|
|
||||||
web3-utils@1.2.1:
|
web3-utils@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.1.tgz#21466e38291551de0ab34558de21512ac4274534"
|
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.4.tgz#96832a39a66b05bf8862a5b0bdad2799d709d951"
|
||||||
|
integrity sha512-+S86Ip+jqfIPQWvw2N/xBQq5JNqCO0dyvukGdJm8fEWHZbckT4WxSpHbx+9KLEWY4H4x9pUwnoRkK87pYyHfgQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
bn.js "4.11.8"
|
bn.js "4.11.8"
|
||||||
eth-lib "0.2.7"
|
eth-lib "0.2.7"
|
||||||
|
ethereum-bloom-filters "^1.0.6"
|
||||||
ethjs-unit "0.1.6"
|
ethjs-unit "0.1.6"
|
||||||
number-to-bn "1.7.0"
|
number-to-bn "1.7.0"
|
||||||
randomhex "0.1.5"
|
randombytes "^2.1.0"
|
||||||
underscore "1.9.1"
|
underscore "1.9.1"
|
||||||
utf8 "3.0.0"
|
utf8 "3.0.0"
|
||||||
|
|
||||||
@ -17437,17 +17531,19 @@ web3-utils@2.0.0-alpha:
|
|||||||
randombytes "^2.1.0"
|
randombytes "^2.1.0"
|
||||||
utf8 "2.1.1"
|
utf8 "2.1.1"
|
||||||
|
|
||||||
web3@1.2.1:
|
web3@1.2.4:
|
||||||
version "1.2.1"
|
version "1.2.4"
|
||||||
resolved "https://registry.npmjs.org/web3/-/web3-1.2.1.tgz#5d8158bcca47838ab8c2b784a2dee4c3ceb4179b"
|
resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.4.tgz#6e7ab799eefc9b4648c2dab63003f704a1d5e7d9"
|
||||||
|
integrity sha512-xPXGe+w0x0t88Wj+s/dmAdASr3O9wmA9mpZRtixGZxmBexAF0MjfqYM+MS4tVl5s11hMTN3AZb8cDD4VLfC57A==
|
||||||
dependencies:
|
dependencies:
|
||||||
web3-bzz "1.2.1"
|
"@types/node" "^12.6.1"
|
||||||
web3-core "1.2.1"
|
web3-bzz "1.2.4"
|
||||||
web3-eth "1.2.1"
|
web3-core "1.2.4"
|
||||||
web3-eth-personal "1.2.1"
|
web3-eth "1.2.4"
|
||||||
web3-net "1.2.1"
|
web3-eth-personal "1.2.4"
|
||||||
web3-shh "1.2.1"
|
web3-net "1.2.4"
|
||||||
web3-utils "1.2.1"
|
web3-shh "1.2.4"
|
||||||
|
web3-utils "1.2.4"
|
||||||
|
|
||||||
webidl-conversions@^4.0.2:
|
webidl-conversions@^4.0.2:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
@ -17606,16 +17702,6 @@ websocket@^1.0.26:
|
|||||||
typedarray-to-buffer "^3.1.5"
|
typedarray-to-buffer "^3.1.5"
|
||||||
yaeti "^0.0.6"
|
yaeti "^0.0.6"
|
||||||
|
|
||||||
"websocket@github:web3-js/WebSocket-Node#polyfill/globalThis":
|
|
||||||
version "1.0.29"
|
|
||||||
resolved "https://codeload.github.com/web3-js/WebSocket-Node/tar.gz/905deb4812572b344f5801f8c9ce8bb02799d82e"
|
|
||||||
dependencies:
|
|
||||||
debug "^2.2.0"
|
|
||||||
es5-ext "^0.10.50"
|
|
||||||
nan "^2.14.0"
|
|
||||||
typedarray-to-buffer "^3.1.5"
|
|
||||||
yaeti "^0.0.6"
|
|
||||||
|
|
||||||
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
|
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
|
resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user