@0x/contracts-zero-ex: Address review feedback.

This commit is contained in:
Lawrence Forman 2020-07-06 12:29:23 -04:00
parent bdc1dbf08a
commit e8106f04b5
14 changed files with 135 additions and 80 deletions

View File

@ -36,7 +36,7 @@ interface IMetaTransactions {
// Maximum gas price. // Maximum gas price.
uint256 maxGasPrice; uint256 maxGasPrice;
// MTX is invalid after this time. // MTX is invalid after this time.
uint256 expirationTime; uint256 expirationTimeSeconds;
// Nonce to make this MTX unique. // Nonce to make this MTX unique.
uint256 salt; uint256 salt;
// Encoded call data to a function on the exchange proxy. // Encoded call data to a function on the exchange proxy.
@ -65,33 +65,33 @@ interface IMetaTransactions {
/// @dev Execute a single meta-transaction. /// @dev Execute a single meta-transaction.
/// @param mtx The meta-transaction. /// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`. /// @param signature The signature by `mtx.signer`.
/// @return returnData The ABI-encoded result of the underlying call. /// @return returnResult The ABI-encoded result of the underlying call.
function executeMetaTransaction( function executeMetaTransaction(
MetaTransactionData calldata mtx, MetaTransactionData calldata mtx,
bytes calldata signature bytes calldata signature
) )
external external
payable payable
returns (bytes memory returnData); returns (bytes memory returnResult);
/// @dev Execute multiple meta-transactions. /// @dev Execute multiple meta-transactions.
/// @param mtxs The meta-transactions. /// @param mtxs The meta-transactions.
/// @param signatures The signature by each respective `mtx.signer`. /// @param signatures The signature by each respective `mtx.signer`.
/// @return returnDatas The ABI-encoded results of the underlying calls. /// @return returnResults The ABI-encoded results of the underlying calls.
function executeMetaTransactions( function batchExecuteMetaTransactions(
MetaTransactionData[] calldata mtxs, MetaTransactionData[] calldata mtxs,
bytes[] calldata signatures bytes[] calldata signatures
) )
external external
payable payable
returns (bytes[] memory returnDatas); returns (bytes[] memory returnResults);
/// @dev Execute a meta-transaction via `sender`. Privileged variant. /// @dev Execute a meta-transaction via `sender`. Privileged variant.
/// Only callable from within. /// Only callable from within.
/// @param sender Who is executing the meta-transaction.. /// @param sender Who is executing the meta-transaction..
/// @param mtx The meta-transaction. /// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`. /// @param signature The signature by `mtx.signer`.
/// @return returnData The ABI-encoded result of the underlying call. /// @return returnResult The ABI-encoded result of the underlying call.
function _executeMetaTransaction( function _executeMetaTransaction(
address sender, address sender,
MetaTransactionData calldata mtx, MetaTransactionData calldata mtx,
@ -99,7 +99,7 @@ interface IMetaTransactions {
) )
external external
payable payable
returns (bytes memory returnData); returns (bytes memory returnResult);
/// @dev Get the block at which a meta-transaction has been executed. /// @dev Get the block at which a meta-transaction has been executed.
/// @param mtx The meta-transaction. /// @param mtx The meta-transaction.

View File

@ -73,7 +73,7 @@ contract MetaTransactions is
"address sender," "address sender,"
"uint256 minGasPrice," "uint256 minGasPrice,"
"uint256 maxGasPrice," "uint256 maxGasPrice,"
"uint256 expirationTime," "uint256 expirationTimeSeconds,"
"uint256 salt," "uint256 salt,"
"bytes callData," "bytes callData,"
"uint256 value," "uint256 value,"
@ -98,7 +98,7 @@ contract MetaTransactions is
returns (bytes4 success) returns (bytes4 success)
{ {
_registerFeatureFunction(this.executeMetaTransaction.selector); _registerFeatureFunction(this.executeMetaTransaction.selector);
_registerFeatureFunction(this.executeMetaTransactions.selector); _registerFeatureFunction(this.batchExecuteMetaTransactions.selector);
_registerFeatureFunction(this._executeMetaTransaction.selector); _registerFeatureFunction(this._executeMetaTransaction.selector);
_registerFeatureFunction(this.getMetaTransactionExecutedBlock.selector); _registerFeatureFunction(this.getMetaTransactionExecutedBlock.selector);
_registerFeatureFunction(this.getMetaTransactionHashExecutedBlock.selector); _registerFeatureFunction(this.getMetaTransactionHashExecutedBlock.selector);
@ -109,7 +109,7 @@ contract MetaTransactions is
/// @dev Execute a single meta-transaction. /// @dev Execute a single meta-transaction.
/// @param mtx The meta-transaction. /// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`. /// @param signature The signature by `mtx.signer`.
/// @return returnData The ABI-encoded result of the underlying call. /// @return returnResult The ABI-encoded result of the underlying call.
function executeMetaTransaction( function executeMetaTransaction(
MetaTransactionData memory mtx, MetaTransactionData memory mtx,
bytes memory signature bytes memory signature
@ -117,7 +117,7 @@ contract MetaTransactions is
public public
payable payable
override override
returns (bytes memory returnData) returns (bytes memory returnResult)
{ {
return _executeMetaTransactionPrivate( return _executeMetaTransactionPrivate(
msg.sender, msg.sender,
@ -129,15 +129,15 @@ contract MetaTransactions is
/// @dev Execute multiple meta-transactions. /// @dev Execute multiple meta-transactions.
/// @param mtxs The meta-transactions. /// @param mtxs The meta-transactions.
/// @param signatures The signature by each respective `mtx.signer`. /// @param signatures The signature by each respective `mtx.signer`.
/// @return returnDatas The ABI-encoded results of the underlying calls. /// @return returnResults The ABI-encoded results of the underlying calls.
function executeMetaTransactions( function batchExecuteMetaTransactions(
MetaTransactionData[] memory mtxs, MetaTransactionData[] memory mtxs,
bytes[] memory signatures bytes[] memory signatures
) )
public public
payable payable
override override
returns (bytes[] memory returnDatas) returns (bytes[] memory returnResults)
{ {
if (mtxs.length != signatures.length) { if (mtxs.length != signatures.length) {
LibMetaTransactionsRichErrors.InvalidMetaTransactionsArrayLengthsError( LibMetaTransactionsRichErrors.InvalidMetaTransactionsArrayLengthsError(
@ -145,9 +145,9 @@ contract MetaTransactions is
signatures.length signatures.length
).rrevert(); ).rrevert();
} }
returnDatas = new bytes[](mtxs.length); returnResults = new bytes[](mtxs.length);
for (uint256 i = 0; i < mtxs.length; ++i) { for (uint256 i = 0; i < mtxs.length; ++i) {
returnDatas[i] = _executeMetaTransactionPrivate( returnResults[i] = _executeMetaTransactionPrivate(
msg.sender, msg.sender,
mtxs[i], mtxs[i],
signatures[i] signatures[i]
@ -160,7 +160,7 @@ contract MetaTransactions is
/// @param sender Who is executing the meta-transaction.. /// @param sender Who is executing the meta-transaction..
/// @param mtx The meta-transaction. /// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`. /// @param signature The signature by `mtx.signer`.
/// @return returnData The ABI-encoded result of the underlying call. /// @return returnResult The ABI-encoded result of the underlying call.
function _executeMetaTransaction( function _executeMetaTransaction(
address sender, address sender,
MetaTransactionData memory mtx, MetaTransactionData memory mtx,
@ -170,7 +170,7 @@ contract MetaTransactions is
payable payable
override override
onlySelf onlySelf
returns (bytes memory returnData) returns (bytes memory returnResult)
{ {
return _executeMetaTransactionPrivate(sender, mtx, signature); return _executeMetaTransactionPrivate(sender, mtx, signature);
} }
@ -214,7 +214,7 @@ contract MetaTransactions is
mtx.sender, mtx.sender,
mtx.minGasPrice, mtx.minGasPrice,
mtx.maxGasPrice, mtx.maxGasPrice,
mtx.expirationTime, mtx.expirationTimeSeconds,
mtx.salt, mtx.salt,
keccak256(mtx.callData), keccak256(mtx.callData),
mtx.value, mtx.value,
@ -227,14 +227,14 @@ contract MetaTransactions is
/// @param sender Who is executing the meta-transaction.. /// @param sender Who is executing the meta-transaction..
/// @param mtx The meta-transaction. /// @param mtx The meta-transaction.
/// @param signature The signature by `mtx.signer`. /// @param signature The signature by `mtx.signer`.
/// @return returnData The ABI-encoded result of the underlying call. /// @return returnResult The ABI-encoded result of the underlying call.
function _executeMetaTransactionPrivate( function _executeMetaTransactionPrivate(
address sender, address sender,
MetaTransactionData memory mtx, MetaTransactionData memory mtx,
bytes memory signature bytes memory signature
) )
private private
returns (bytes memory returnData) returns (bytes memory returnResult)
{ {
ExecuteState memory state; ExecuteState memory state;
state.sender = sender; state.sender = sender;
@ -252,7 +252,7 @@ contract MetaTransactions is
// Execute the call based on the selector. // Execute the call based on the selector.
state.selector = mtx.callData.readBytes4(0); state.selector = mtx.callData.readBytes4(0);
if (state.selector == ITransformERC20.transformERC20.selector) { if (state.selector == ITransformERC20.transformERC20.selector) {
returnData = _executeTransformERC20Call(state); returnResult = _executeTransformERC20Call(state);
} else { } else {
LibMetaTransactionsRichErrors LibMetaTransactionsRichErrors
.MetaTransactionUnsupportedFunctionError(state.hash, state.selector) .MetaTransactionUnsupportedFunctionError(state.hash, state.selector)
@ -290,12 +290,12 @@ contract MetaTransactions is
).rrevert(); ).rrevert();
} }
// Must not be expired. // Must not be expired.
if (state.mtx.expirationTime <= block.timestamp) { if (state.mtx.expirationTimeSeconds <= block.timestamp) {
LibMetaTransactionsRichErrors LibMetaTransactionsRichErrors
.MetaTransactionExpiredError( .MetaTransactionExpiredError(
state.hash, state.hash,
block.timestamp, block.timestamp,
state.mtx.expirationTime state.mtx.expirationTimeSeconds
).rrevert(); ).rrevert();
} }
// Must have a valid gas price. // Must have a valid gas price.
@ -349,12 +349,36 @@ contract MetaTransactions is
/// the taker address. /// the taker address.
function _executeTransformERC20Call(ExecuteState memory state) function _executeTransformERC20Call(ExecuteState memory state)
private private
returns (bytes memory returnData) returns (bytes memory returnResult)
{ {
// HACK(dorothy-zbornak): `abi.decode()` with the individual args // HACK(dorothy-zbornak): `abi.decode()` with the individual args
// will cause a stack overflow. But we can prefix the call data with an // will cause a stack overflow. But we can prefix the call data with an
// offset to transform it into the encoding for the equivalent single struct arg. // offset to transform it into the encoding for the equivalent single struct arg,
// Decoding a single struct consumes far less stack space. // since decoding a single struct arg consumes far less stack space than
// decoding multiple struct args.
// Where the encoding for multiple args (with the seleector ommitted)
// would typically look like:
// | argument | offset |
// |--------------------------|---------|
// | inputToken | 0 |
// | outputToken | 32 |
// | inputTokenAmount | 64 |
// | minOutputTokenAmount | 96 |
// | transformations (offset) | 128 | = 32
// | transformations (data) | 160 |
// We will ABI-decode a single struct arg copy with the layout:
// | argument | offset |
// |--------------------------|---------|
// | (arg 1 offset) | 0 | = 32
// | inputToken | 32 |
// | outputToken | 64 |
// | inputTokenAmount | 96 |
// | minOutputTokenAmount | 128 |
// | transformations (offset) | 160 | = 32
// | transformations (data) | 192 |
TransformERC20Args memory args; TransformERC20Args memory args;
{ {
bytes memory encodedStructArgs = new bytes(state.mtx.callData.length - 4 + 32); bytes memory encodedStructArgs = new bytes(state.mtx.callData.length - 4 + 32);
@ -397,15 +421,15 @@ contract MetaTransactions is
/// Warning: Do not let unadulerated `callData` into this function. /// Warning: Do not let unadulerated `callData` into this function.
function _callSelf(bytes32 hash, bytes memory callData, uint256 value) function _callSelf(bytes32 hash, bytes memory callData, uint256 value)
private private
returns (bytes memory returnData) returns (bytes memory returnResult)
{ {
bool success; bool success;
(success, returnData) = address(this).call{value: value}(callData); (success, returnResult) = address(this).call{value: value}(callData);
if (!success) { if (!success) {
LibMetaTransactionsRichErrors.MetaTransactionCallFailedError( LibMetaTransactionsRichErrors.MetaTransactionCallFailedError(
hash, hash,
callData, callData,
returnData returnResult
).rrevert(); ).rrevert();
} }
} }

View File

@ -35,7 +35,7 @@ contract SimpleFunctionRegistry is
ISimpleFunctionRegistry, ISimpleFunctionRegistry,
FixinCommon FixinCommon
{ {
// solhint-disable /// @dev Name of this feature.
string public constant override FEATURE_NAME = "SimpleFunctionRegistry"; string public constant override FEATURE_NAME = "SimpleFunctionRegistry";
/// @dev Version of this feature. /// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0); uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);

View File

@ -49,20 +49,20 @@ contract FullMigration {
address transformerDeployer; address transformerDeployer;
} }
/// @dev The allowed caller of `deploy()`. /// @dev The allowed caller of `initializeZeroEx()`.
address public immutable deployer; address public immutable initializeCaller;
/// @dev The initial migration contract. /// @dev The initial migration contract.
InitialMigration private _initialMigration; InitialMigration private _initialMigration;
/// @dev Instantiate this contract and set the allowed caller of `deploy()` /// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()`
/// to `deployer`. /// to `initializeCaller`.
/// @param deployer_ The allowed caller of `deploy()`. /// @param initializeCaller_ The allowed caller of `initializeZeroEx()`.
constructor(address payable deployer_) constructor(address payable initializeCaller_)
public public
{ {
deployer = deployer_; initializeCaller = initializeCaller_;
// Create an initial migration contract with this contract set to the // Create an initial migration contract with this contract set to the
// allowed deployer. // allowed `initializeCaller`.
_initialMigration = new InitialMigration(address(this)); _initialMigration = new InitialMigration(address(this));
} }
@ -76,7 +76,7 @@ contract FullMigration {
return address(_initialMigration); return address(_initialMigration);
} }
/// @dev Deploy the `ZeroEx` contract with the full feature set, /// @dev Initialize the `ZeroEx` contract with the full feature set,
/// transfer ownership to `owner`, then self-destruct. /// transfer ownership to `owner`, then self-destruct.
/// @param owner The owner of the contract. /// @param owner The owner of the contract.
/// @param zeroEx The instance of the ZeroEx contract. ZeroEx should /// @param zeroEx The instance of the ZeroEx contract. ZeroEx should
@ -84,7 +84,7 @@ contract FullMigration {
/// @param features Features to add to the proxy. /// @param features Features to add to the proxy.
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter. /// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter.
/// @param migrateOpts Parameters needed to initialize features. /// @param migrateOpts Parameters needed to initialize features.
function deploy( function initializeZeroEx(
address payable owner, address payable owner,
ZeroEx zeroEx, ZeroEx zeroEx,
Features memory features, Features memory features,
@ -93,10 +93,10 @@ contract FullMigration {
public public
returns (ZeroEx _zeroEx) returns (ZeroEx _zeroEx)
{ {
require(msg.sender == deployer, "FullMigration/INVALID_SENDER"); require(msg.sender == initializeCaller, "FullMigration/INVALID_SENDER");
// Perform the initial migration with the owner set to this contract. // Perform the initial migration with the owner set to this contract.
_initialMigration.deploy( _initialMigration.initializeZeroEx(
address(uint160(address(this))), address(uint160(address(this))),
zeroEx, zeroEx,
InitialMigration.BootstrapFeatures({ InitialMigration.BootstrapFeatures({
@ -117,7 +117,7 @@ contract FullMigration {
return zeroEx; return zeroEx;
} }
/// @dev Destroy this contract. Only callable from ourselves (from `deploy()`). /// @dev Destroy this contract. Only callable from ourselves (from `initializeZeroEx()`).
/// @param ethRecipient Receiver of any ETH in this contract. /// @param ethRecipient Receiver of any ETH in this contract.
function die(address payable ethRecipient) function die(address payable ethRecipient)
external external

View File

@ -35,29 +35,29 @@ contract InitialMigration {
Ownable ownable; Ownable ownable;
} }
/// @dev The allowed caller of `deploy()`. In production, this would be /// @dev The allowed caller of `initializeZeroEx()`. In production, this would be
/// the governor. /// the governor.
address public immutable deployer; address public immutable initializeCaller;
/// @dev The real address of this contract. /// @dev The real address of this contract.
address private immutable _implementation; address private immutable _implementation;
/// @dev Instantiate this contract and set the allowed caller of `deploy()` /// @dev Instantiate this contract and set the allowed caller of `initializeZeroEx()`
/// to `deployer_`. /// to `initializeCaller_`.
/// @param deployer_ The allowed caller of `deploy()`. /// @param initializeCaller_ The allowed caller of `initializeZeroEx()`.
constructor(address deployer_) public { constructor(address initializeCaller_) public {
deployer = deployer_; initializeCaller = initializeCaller_;
_implementation = address(this); _implementation = address(this);
} }
/// @dev Deploy the `ZeroEx` contract with the minimum feature set, /// @dev Initialize the `ZeroEx` contract with the minimum feature set,
/// 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 `initializeCaller` set in the contstructor.
/// @param owner The owner of the contract. /// @param owner The owner of the contract.
/// @param zeroEx The instance of the ZeroEx contract. ZeroEx should /// @param zeroEx The instance of the ZeroEx contract. ZeroEx should
/// been constructed with this contract as the bootstrapper. /// been constructed with this contract as the bootstrapper.
/// @param features Features to bootstrap into the proxy. /// @param features Features to bootstrap into the proxy.
/// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter. /// @return _zeroEx The configured ZeroEx contract. Same as the `zeroEx` parameter.
function deploy( function initializeZeroEx(
address payable owner, address payable owner,
ZeroEx zeroEx, ZeroEx zeroEx,
BootstrapFeatures memory features BootstrapFeatures memory features
@ -66,8 +66,8 @@ contract InitialMigration {
virtual virtual
returns (ZeroEx _zeroEx) returns (ZeroEx _zeroEx)
{ {
// Must be called by the allowed deployer. // Must be called by the allowed initializeCaller.
require(msg.sender == deployer, "InitialMigration/INVALID_SENDER"); require(msg.sender == initializeCaller, "InitialMigration/INVALID_SENDER");
// Bootstrap the initial feature set. // Bootstrap the initial feature set.
IBootstrap(address(zeroEx)).bootstrap( IBootstrap(address(zeroEx)).bootstrap(

View File

@ -39,9 +39,9 @@
"publish:private": "yarn build && gitpkg publish" "publish:private": "yarn build && gitpkg publish"
}, },
"config": { "config": {
"publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer,Ownable,SimpleFunctionRegistry,TransformERC20,TokenSpender,AffiliateFeeTransformerSignatureValidator,MetaTransactions", "publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer,Ownable,SimpleFunctionRegistry,TransformERC20,TokenSpender,AffiliateFeeTransformer,SignatureValidator,MetaTransactions",
"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/@(AffiliateFeeTransformer|AllowanceTarget|Bootstrap|FillQuoteTransformer|FixinCommon|FixinEIP712|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Transformer|IExchange|IFeature|IFlashWallet|IMetaTransactions|IOwnable|ISignatureValidator|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|MetaTransactions|Ownable|PayTakerTransformer|SignatureValidator|SimpleFunctionRegistry|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|Transformer|TransformerDeployer|WethTransformer|ZeroEx).json" "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|Bootstrap|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinGasToken|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|IMetaTransactions|IOwnable|ISignatureValidator|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|MetaTransactions|Ownable|PayTakerTransformer|SignatureValidator|SimpleFunctionRegistry|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|Transformer|TransformerDeployer|WethTransformer|ZeroEx).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -73,7 +73,7 @@ export async function initialMigrateAsync(
migrator.address, migrator.address,
); );
const _features = await deployBootstrapFeaturesAsync(provider, txDefaults, features); const _features = await deployBootstrapFeaturesAsync(provider, txDefaults, features);
await migrator.deploy(owner, zeroEx.address, _features).awaitTransactionSuccessAsync(); await migrator.initializeZeroEx(owner, zeroEx.address, _features).awaitTransactionSuccessAsync();
return zeroEx; return zeroEx;
} }
@ -170,6 +170,6 @@ export async function fullMigrateAsync(
transformerDeployer: txDefaults.from as string, transformerDeployer: txDefaults.from as string,
...opts, ...opts,
}; };
await migrator.deploy(owner, zeroEx.address, _features, _opts).awaitTransactionSuccessAsync(); await migrator.initializeZeroEx(owner, zeroEx.address, _features, _opts).awaitTransactionSuccessAsync();
return zeroEx; return zeroEx;
} }

View File

@ -10,8 +10,8 @@ import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.js
import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json'; import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json';
import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json'; import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json';
import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json'; import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json';
import * as FixinGasToken from '../test/generated-artifacts/FixinGasToken.json';
import * as FixinEIP712 from '../test/generated-artifacts/FixinEIP712.json'; import * as FixinEIP712 from '../test/generated-artifacts/FixinEIP712.json';
import * as FixinGasToken from '../test/generated-artifacts/FixinGasToken.json';
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json'; import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
import * as FullMigration from '../test/generated-artifacts/FullMigration.json'; import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json'; import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json';
@ -114,8 +114,8 @@ export const artifacts = {
TokenSpender: TokenSpender as ContractArtifact, TokenSpender: TokenSpender as ContractArtifact,
TransformERC20: TransformERC20 as ContractArtifact, TransformERC20: TransformERC20 as ContractArtifact,
FixinCommon: FixinCommon as ContractArtifact, FixinCommon: FixinCommon as ContractArtifact,
FixinGasToken: FixinGasToken as ContractArtifact,
FixinEIP712: FixinEIP712 as ContractArtifact, FixinEIP712: FixinEIP712 as ContractArtifact,
FixinGasToken: FixinGasToken as ContractArtifact,
FullMigration: FullMigration as ContractArtifact, FullMigration: FullMigration as ContractArtifact,
InitialMigration: InitialMigration as ContractArtifact, InitialMigration: InitialMigration as ContractArtifact,
LibBootstrap: LibBootstrap as ContractArtifact, LibBootstrap: LibBootstrap as ContractArtifact,

View File

@ -74,7 +74,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
sender, sender,
minGasPrice: getRandomInteger('2', '1e9'), minGasPrice: getRandomInteger('2', '1e9'),
maxGasPrice: getRandomInteger('1e9', '100e9'), maxGasPrice: getRandomInteger('1e9', '100e9'),
expirationTime: new BigNumber(Math.floor(_.now() / 1000) + 360), expirationTimeSeconds: new BigNumber(Math.floor(_.now() / 1000) + 360),
salt: new BigNumber(hexUtils.random()), salt: new BigNumber(hexUtils.random()),
callData: hexUtils.random(4), callData: hexUtils.random(4),
value: getRandomInteger(1, '1e18'), value: getRandomInteger(1, '1e18'),
@ -362,7 +362,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
it('fails if expired', async () => { it('fails if expired', async () => {
const mtx = getRandomMetaTransaction({ const mtx = getRandomMetaTransaction({
expirationTime: new BigNumber(Math.floor(_.now() / 1000 - 60)), expirationTimeSeconds: new BigNumber(Math.floor(_.now() / 1000 - 60)),
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
const signature = await signMetaTransactionAsync(mtx); const signature = await signMetaTransactionAsync(mtx);
@ -375,7 +375,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
new ZeroExRevertErrors.MetaTransactions.MetaTransactionExpiredError( new ZeroExRevertErrors.MetaTransactions.MetaTransactionExpiredError(
mtxHash, mtxHash,
undefined, undefined,
mtx.expirationTime, mtx.expirationTimeSeconds,
), ),
); );
}); });
@ -425,7 +425,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
}); });
}); });
describe('executeMetaTransactions()', () => { describe('batchExecuteMetaTransactions()', () => {
it('can execute multiple transactions', async () => { it('can execute multiple transactions', async () => {
const mtxs = _.times(2, i => { const mtxs = _.times(2, i => {
const args = getRandomTransformERC20Args(); const args = getRandomTransformERC20Args();
@ -447,9 +447,39 @@ blockchainTests.resets('MetaTransactions feature', env => {
gasPrice: BigNumber.max(...mtxs.map(mtx => mtx.minGasPrice)), gasPrice: BigNumber.max(...mtxs.map(mtx => mtx.minGasPrice)),
value: BigNumber.sum(...mtxs.map(mtx => mtx.value)), value: BigNumber.sum(...mtxs.map(mtx => mtx.value)),
}; };
const rawResults = await feature.executeMetaTransactions(mtxs, signatures).callAsync(callOpts); const rawResults = await feature.batchExecuteMetaTransactions(mtxs, signatures).callAsync(callOpts);
expect(rawResults).to.eql(mtxs.map(() => RAW_SUCCESS_RESULT)); expect(rawResults).to.eql(mtxs.map(() => RAW_SUCCESS_RESULT));
}); });
it('cannot execute the same transaction twice', async () => {
const mtx = (() => {
const args = getRandomTransformERC20Args();
return getRandomMetaTransaction({
signer: _.sampleSize(signers, 1)[0],
callData: transformERC20Feature
.transformERC20(
args.inputToken,
args.outputToken,
args.inputTokenAmount,
args.minOutputTokenAmount,
args.transformations,
)
.getABIEncodedTransactionData(),
});
})();
const mtxHash = getExchangeProxyMetaTransactionHash(mtx);
const mtxs = _.times(2, () => mtx);
const signatures = await Promise.all(mtxs.map(async mtx => signMetaTransactionAsync(mtx)));
const callOpts = {
gasPrice: BigNumber.max(...mtxs.map(mtx => mtx.minGasPrice)),
value: BigNumber.sum(...mtxs.map(mtx => mtx.value)),
};
const block = await env.web3Wrapper.getBlockNumberAsync();
const tx = feature.batchExecuteMetaTransactions(mtxs, signatures).callAsync(callOpts);
return expect(tx).to.revertWith(
new ZeroExRevertErrors.MetaTransactions.MetaTransactionAlreadyExecutedError(mtxHash, block),
);
});
}); });
describe('getMetaTransactionExecutedBlock()', () => { describe('getMetaTransactionExecutedBlock()', () => {

View File

@ -66,13 +66,12 @@ blockchainTests.resets('SignatureValidator feature', env => {
const hash = hexUtils.random(); const hash = hexUtils.random();
const signer = _.sampleSize(signers, 1)[0]; const signer = _.sampleSize(signers, 1)[0];
const signature = hexUtils.slice(await signatureUtils.ecSignHashAsync(env.provider, hash, signer), 1); const signature = hexUtils.slice(await signatureUtils.ecSignHashAsync(env.provider, hash, signer), 1);
const notSigner = randomAddress(); const tx = feature.validateHashSignature(hash, signer, signature).callAsync();
const tx = feature.validateHashSignature(hash, notSigner, signature).callAsync();
return expect(tx).to.revertWith( return expect(tx).to.revertWith(
new ZeroExRevertErrors.SignatureValidator.SignatureValidationError( new ZeroExRevertErrors.SignatureValidator.SignatureValidationError(
ZeroExRevertErrors.SignatureValidator.SignatureValidationErrorCodes.InvalidLength, ZeroExRevertErrors.SignatureValidator.SignatureValidationErrorCodes.InvalidLength,
hash, hash,
notSigner, signer,
signature, signature,
), ),
); );

View File

@ -44,7 +44,9 @@ blockchainTests.resets('Full migration', env => {
await migrator.getBootstrapper().callAsync(), await migrator.getBootstrapper().callAsync(),
); );
features = await deployFullFeaturesAsync(env.provider, env.txDefaults, zeroEx.address); features = await deployFullFeaturesAsync(env.provider, env.txDefaults, zeroEx.address);
await migrator.deploy(owner, zeroEx.address, features, { transformerDeployer }).awaitTransactionSuccessAsync(); await migrator
.initializeZeroEx(owner, zeroEx.address, features, { transformerDeployer })
.awaitTransactionSuccessAsync();
}); });
it('ZeroEx has the correct owner', async () => { it('ZeroEx has the correct owner', async () => {
@ -58,10 +60,10 @@ blockchainTests.resets('Full migration', env => {
expect(dieRecipient).to.eq(owner); expect(dieRecipient).to.eq(owner);
}); });
it('Non-deployer cannot call deploy()', async () => { it('Non-deployer cannot call initializeZeroEx()', async () => {
const notDeployer = randomAddress(); const notDeployer = randomAddress();
const tx = migrator const tx = migrator
.deploy(owner, zeroEx.address, features, { transformerDeployer }) .initializeZeroEx(owner, zeroEx.address, features, { transformerDeployer })
.callAsync({ from: notDeployer }); .callAsync({ from: notDeployer });
return expect(tx).to.revertWith('FullMigration/INVALID_SENDER'); return expect(tx).to.revertWith('FullMigration/INVALID_SENDER');
}); });
@ -89,7 +91,7 @@ blockchainTests.resets('Full migration', env => {
contractType: IMetaTransactionsContract, contractType: IMetaTransactionsContract,
fns: [ fns: [
'executeMetaTransaction', 'executeMetaTransaction',
'executeMetaTransactions', 'batchExecuteMetaTransactions',
'_executeMetaTransaction', '_executeMetaTransaction',
'getMetaTransactionExecutedBlock', 'getMetaTransactionExecutedBlock',
'getMetaTransactionHashExecutedBlock', 'getMetaTransactionHashExecutedBlock',

View File

@ -42,7 +42,7 @@ blockchainTests.resets('Initial migration', env => {
artifacts, artifacts,
migrator.address, migrator.address,
); );
await migrator.deploy(owner, zeroEx.address, features).awaitTransactionSuccessAsync(); await migrator.initializeZeroEx(owner, zeroEx.address, features).awaitTransactionSuccessAsync();
}); });
it('Self-destructs after deployment', async () => { it('Self-destructs after deployment', async () => {
@ -50,9 +50,9 @@ blockchainTests.resets('Initial migration', env => {
expect(dieRecipient).to.eq(owner); expect(dieRecipient).to.eq(owner);
}); });
it('Non-deployer cannot call deploy()', async () => { it('Non-deployer cannot call initializeZeroEx()', async () => {
const notDeployer = randomAddress(); const notDeployer = randomAddress();
const tx = migrator.deploy(owner, zeroEx.address, features).callAsync({ from: notDeployer }); const tx = migrator.initializeZeroEx(owner, zeroEx.address, features).callAsync({ from: notDeployer });
return expect(tx).to.revertWith('InitialMigration/INVALID_SENDER'); return expect(tx).to.revertWith('InitialMigration/INVALID_SENDER');
}); });

View File

@ -8,8 +8,8 @@ export * from '../test/generated-wrappers/allowance_target';
export * from '../test/generated-wrappers/bootstrap'; export * from '../test/generated-wrappers/bootstrap';
export * from '../test/generated-wrappers/fill_quote_transformer'; export * from '../test/generated-wrappers/fill_quote_transformer';
export * from '../test/generated-wrappers/fixin_common'; export * from '../test/generated-wrappers/fixin_common';
export * from '../test/generated-wrappers/fixin_gas_token';
export * from '../test/generated-wrappers/fixin_e_i_p712'; export * from '../test/generated-wrappers/fixin_e_i_p712';
export * from '../test/generated-wrappers/fixin_gas_token';
export * from '../test/generated-wrappers/flash_wallet'; export * from '../test/generated-wrappers/flash_wallet';
export * from '../test/generated-wrappers/full_migration'; export * from '../test/generated-wrappers/full_migration';
export * from '../test/generated-wrappers/i_allowance_target'; export * from '../test/generated-wrappers/i_allowance_target';

View File

@ -28,8 +28,8 @@
"test/generated-artifacts/Bootstrap.json", "test/generated-artifacts/Bootstrap.json",
"test/generated-artifacts/FillQuoteTransformer.json", "test/generated-artifacts/FillQuoteTransformer.json",
"test/generated-artifacts/FixinCommon.json", "test/generated-artifacts/FixinCommon.json",
"test/generated-artifacts/FixinGasToken.json",
"test/generated-artifacts/FixinEIP712.json", "test/generated-artifacts/FixinEIP712.json",
"test/generated-artifacts/FixinGasToken.json",
"test/generated-artifacts/FlashWallet.json", "test/generated-artifacts/FlashWallet.json",
"test/generated-artifacts/FullMigration.json", "test/generated-artifacts/FullMigration.json",
"test/generated-artifacts/IAllowanceTarget.json", "test/generated-artifacts/IAllowanceTarget.json",