remove calldata signing (#51)

This commit is contained in:
Steve Marx 2020-11-25 16:55:12 -05:00 committed by GitHub
parent 9653eb9e70
commit 88d7e73eba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 31 additions and 549 deletions

View File

@ -7,7 +7,6 @@ import {
IZeroExContract,
LogMetadataTransformerContract,
Signature,
signCallData,
} from '@0x/contracts-zero-ex';
import { migrateOnceAsync } from '@0x/migrations';
import {
@ -21,10 +20,10 @@ import {
SignedExchangeProxyMetaTransaction,
} from '@0x/order-utils';
import { AssetProxyId, Order, SignedOrder } from '@0x/types';
import { BigNumber, hexUtils, ZeroExRevertErrors } from '@0x/utils';
import { BigNumber, hexUtils } from '@0x/utils';
import * as ethjs from 'ethereumjs-util';
const { MAX_UINT256, NULL_ADDRESS, NULL_BYTES, NULL_BYTES32, ZERO_AMOUNT } = constants;
const { MAX_UINT256, NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
function sigstruct(signature: string): Signature {
return {
@ -198,21 +197,6 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
.getABIEncodedTransactionData();
}
function getSignedSwapData(swap: SwapInfo, signerKey?: string): string {
return signCallData(
zeroEx
.transformERC20(
swap.inputTokenAddress,
swap.outputTokenAddress,
swap.inputTokenAmount,
swap.minOutputTokenAmount,
swap.transformations,
)
.getABIEncodedTransactionData(),
signerKey ? signerKey : quoteSignerKey,
);
}
async function createMetaTransactionAsync(
data: string,
value: BigNumber,
@ -242,12 +226,10 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
);
}
it('can call `transformERC20()` with signed calldata and no relayer fee', async () => {
it('can call `transformERC20()` with calldata and no relayer fee', async () => {
const swap = await generateSwapAsync();
const callDataHash = hexUtils.hash(getSwapData(swap));
const signedSwapData = getSignedSwapData(swap);
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee, 0);
const mtx = await createMetaTransactionAsync(getSwapData(swap), _protocolFee, 0);
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
const receipt = await zeroEx
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
@ -269,7 +251,6 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
[
{
taker,
callDataHash,
sender: zeroEx.address,
data: NULL_BYTES,
},
@ -278,12 +259,10 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
);
});
it('can call `transformERC20()` with signed calldata and a relayer fee', async () => {
it('can call `transformERC20()` with calldata and a relayer fee', async () => {
const swap = await generateSwapAsync();
const callDataHash = hexUtils.hash(getSwapData(swap));
const signedSwapData = getSignedSwapData(swap);
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee);
const mtx = await createMetaTransactionAsync(getSwapData(swap), _protocolFee);
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
const receipt = await zeroEx
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
@ -305,7 +284,6 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
[
{
taker,
callDataHash,
sender: zeroEx.address,
data: NULL_BYTES,
},
@ -314,48 +292,10 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
);
});
it('can call `transformERC20()` with wrongly signed calldata and a relayer fee', async () => {
const swap = await generateSwapAsync();
const signedSwapData = getSignedSwapData(swap, hexUtils.random());
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee);
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
const receipt = await zeroEx
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
const relayerEthRefund = relayerEthBalanceBefore
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
.minus(GAS_PRICE.times(receipt.gasUsed));
// Ensure the relayer got back the unused protocol fees.
expect(relayerEthRefund).to.bignumber.eq(protocolFee.times(GAS_PRICE));
// Ensure the relayer got paid mtx fees.
expect(await feeToken.balanceOf(relayer).callAsync()).to.bignumber.eq(mtx.feeAmount);
// Ensure the taker got output tokens.
expect(await outputToken.balanceOf(taker).callAsync()).to.bignumber.eq(swap.minOutputTokenAmount);
// Ensure the maker got input tokens.
expect(await inputToken.balanceOf(maker).callAsync()).to.bignumber.eq(swap.inputTokenAmount);
// Check events.
verifyEventsFromLogs(
receipt.logs,
[
{
taker,
// Only signed calldata should have a nonzero hash.
callDataHash: NULL_BYTES32,
sender: zeroEx.address,
data: NULL_BYTES,
},
],
'TransformerMetadata',
);
});
it('`transformERC20()` can fill RFQT order if calldata is signed', async () => {
it('`transformERC20()` can fill RFQT order', async () => {
const swap = await generateSwapAsync({}, true);
const callDataHash = hexUtils.hash(getSwapData(swap));
const signedSwapData = getSignedSwapData(swap);
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee, 0);
const mtx = await createMetaTransactionAsync(getSwapData(swap), _protocolFee, 0);
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
const receipt = await zeroEx
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
@ -377,7 +317,6 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
[
{
taker,
callDataHash,
sender: zeroEx.address,
data: NULL_BYTES,
},
@ -386,10 +325,9 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
);
});
it('`transformERC20()` can fill RFQT order if calldata is not signed but no quote signer configured', async () => {
it('`transformERC20()` can fill RFQT order if quote signer configured', async () => {
const swap = await generateSwapAsync({}, true);
const callData = getSwapData(swap);
const callDataHash = hexUtils.hash(callData);
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
const mtx = await createMetaTransactionAsync(callData, _protocolFee, 0);
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
@ -414,7 +352,6 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
[
{
taker,
callDataHash,
sender: zeroEx.address,
data: NULL_BYTES,
},
@ -422,15 +359,4 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
'TransformerMetadata',
);
});
it('`transformERC20()` cannot fill RFQT order if calldata is not signed', async () => {
const swap = await generateSwapAsync({}, true);
const callData = getSwapData(swap);
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
const mtx = await createMetaTransactionAsync(callData, _protocolFee, 0);
const tx = zeroEx
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
return expect(tx).to.revertWith(new ZeroExRevertErrors.MetaTransactions.MetaTransactionCallFailedError());
});
});

View File

@ -45,6 +45,10 @@
{
"note": "Fix getRfqOrderInfo() to return status INVALID when missing txOrigin",
"pr": 50
},
{
"note": "Remove calldata signing functionality",
"pr": 51
}
]
},

View File

@ -58,10 +58,6 @@ interface ITransformERC20Feature {
// The transformations to execute on the token balance(s)
// in sequence.
Transformation[] transformations;
// The hash of the calldata for the `transformERC20()` call.
bytes32 callDataHash;
// The signature for `callDataHash` signed by `getQuoteSigner()`.
bytes callDataSignature;
}
/// @dev Raised upon a successful `transformERC20`.

View File

@ -29,7 +29,6 @@ import "../fixins/FixinTokenSpender.sol";
import "../fixins/FixinEIP712.sol";
import "../migrations/LibMigrate.sol";
import "../storage/LibMetaTransactionsStorage.sol";
import "./libs/LibSignedCallData.sol";
import "./IMetaTransactionsFeature.sol";
import "./ITransformERC20Feature.sol";
import "./libs/LibSignature.sol";
@ -433,10 +432,6 @@ contract MetaTransactionsFeature is
// Decode call args for `ITransformERC20Feature.transformERC20()` as a struct.
args = abi.decode(encodedStructArgs, (ExternalTransformERC20Args));
}
// Parse the signature and hash out of the calldata so `_transformERC20()`
// can authenticate it.
(bytes32 callDataHash, bytes memory callDataSignature) =
LibSignedCallData.parseCallData(state.mtx.callData);
// Call `ITransformERC20Feature._transformERC20()` (internal variant).
return _callSelf(
state.hash,
@ -448,9 +443,7 @@ contract MetaTransactionsFeature is
outputToken: args.outputToken,
inputTokenAmount: args.inputTokenAmount,
minOutputTokenAmount: args.minOutputTokenAmount,
transformations: args.transformations,
callDataHash: callDataHash,
callDataSignature: callDataSignature
transformations: args.transformations
})
),
state.mtx.value

View File

@ -32,7 +32,6 @@ import "../external/FlashWallet.sol";
import "../storage/LibTransformERC20Storage.sol";
import "../transformers/IERC20Transformer.sol";
import "../transformers/LibERC20Transformer.sol";
import "./libs/LibSignedCallData.sol";
import "./ITransformERC20Feature.sol";
import "./IFeature.sol";
import "./ISignatureValidatorFeature.sol";
@ -177,8 +176,6 @@ contract TransformERC20Feature is
payable
returns (uint256 outputTokenAmount)
{
(bytes32 callDataHash, bytes memory callDataSignature) =
LibSignedCallData.parseCallData(msg.data);
return _transformERC20Private(
TransformERC20Args({
taker: msg.sender,
@ -186,9 +183,7 @@ contract TransformERC20Feature is
outputToken: outputToken,
inputTokenAmount: inputTokenAmount,
minOutputTokenAmount: minOutputTokenAmount,
transformations: transformations,
callDataHash: callDataHash,
callDataSignature: callDataSignature
transformations: transformations
})
);
}
@ -246,22 +241,13 @@ contract TransformERC20Feature is
);
{
// Validate that the calldata was signed by the quote signer.
// `validCallDataHash` will be 0x0 if not.
bytes32 validCallDataHash = _getValidCallDataHash(
args.callDataHash,
args.callDataSignature
);
// Perform transformations.
for (uint256 i = 0; i < args.transformations.length; ++i) {
_executeTransformation(
state.wallet,
args.transformations[i],
state.transformerDeployer,
args.taker,
// Transformers will receive a null calldata hash if
// the calldata was not properly signed.
validCallDataHash
args.taker
);
}
}
@ -349,13 +335,11 @@ contract TransformERC20Feature is
/// @param transformation The transformation.
/// @param transformerDeployer The address of the transformer deployer.
/// @param taker The taker address.
/// @param callDataHash Hash of the calldata.
function _executeTransformation(
IFlashWallet wallet,
Transformation memory transformation,
address transformerDeployer,
address payable taker,
bytes32 callDataHash
address payable taker
)
private
{
@ -372,7 +356,6 @@ contract TransformERC20Feature is
abi.encodeWithSelector(
IERC20Transformer.transform.selector,
IERC20Transformer.TransformContext({
callDataHash: callDataHash,
sender: msg.sender,
taker: taker,
data: transformation.data

View File

@ -1,72 +0,0 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
/// @dev Library for working with signed calldata.
library LibSignedCallData {
using LibBytesV06 for bytes;
// bytes4(keccak256('SignedCallDataSignature(bytes)'))
bytes4 constant private SIGNATURE_SELECTOR = 0xf86d1d92;
/// @dev Try to parse potentially signed calldata into its hash and signature
/// components. Signed calldata has signature data appended to it.
/// @param callData the raw call data.
/// @return callDataHash If a signature is detected, this will be the hash of
/// the bytes preceding the signature data. Otherwise, this
/// will be the hash of the entire `callData`.
/// @return signature The signature bytes, if present.
function parseCallData(bytes memory callData)
internal
pure
returns (bytes32 callDataHash, bytes memory signature)
{
// Signed calldata has a 70 byte signature appended as:
// ```
// abi.encodePacked(
// callData,
// bytes4(keccak256('SignedCallDataSignature(bytes)')),
// signature // 66 bytes
// );
// ```
// Try to detect an appended signature. This isn't foolproof, but an
// accidental false positive should highly unlikely. Additinally, the
// signature would also have to pass verification, so the risk here is
// low.
if (
// Signed callData has to be at least 70 bytes long.
callData.length < 70 ||
// The bytes4 at offset -70 should equal `SIGNATURE_SELECTOR`.
SIGNATURE_SELECTOR != callData.readBytes4(callData.length - 70)
) {
return (keccak256(callData), signature);
}
// Consider everything before the signature selector as the original
// calldata and everything after as the signature.
assembly {
callDataHash := keccak256(add(callData, 32), sub(mload(callData), 70))
}
signature = callData.slice(callData.length - 66, callData.length);
}
}

View File

@ -180,10 +180,10 @@ contract FillQuoteTransformer is
state.protocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice);
state.ethRemaining = address(this).balance;
// RFQT orders can only be filled if we have a valid calldata hash
// (calldata was signed), and the actual taker matches the RFQT taker (if set).
state.isRfqtAllowed = context.callDataHash != bytes32(0)
&& (data.rfqtTakerAddress == address(0) || context.taker == data.rfqtTakerAddress);
// RFQT orders can only be filled if the actual taker matches the RFQT
// taker (if set).
state.isRfqtAllowed = data.rfqtTakerAddress == address(0)
|| context.taker == data.rfqtTakerAddress;
// Fill the orders.
for (uint256 i = 0; i < data.orders.length; ++i) {

View File

@ -27,9 +27,6 @@ interface IERC20Transformer {
/// @dev Context information to pass into `transform()` by `TransformERC20.transformERC20()`.
struct TransformContext {
// The hash of the `TransformERC20.transformERC20()` calldata.
// Will be null if the calldata is not signed.
bytes32 callDataHash;
// The caller of `TransformERC20.transformERC20()`.
address payable sender;
// taker The taker address, which may be distinct from `sender` in the case

View File

@ -27,7 +27,7 @@ import "./LibERC20Transformer.sol";
contract LogMetadataTransformer is
Transformer
{
event TransformerMetadata(bytes32 callDataHash, address sender, address taker, bytes data);
event TransformerMetadata(address sender, address taker, bytes data);
/// @dev Maximum uint256 value.
uint256 private constant MAX_UINT256 = uint256(-1);
@ -40,7 +40,7 @@ contract LogMetadataTransformer is
override
returns (bytes4 success)
{
emit TransformerMetadata(context.callDataHash, context.sender, context.taker, context.data);
emit TransformerMetadata(context.sender, context.taker, context.data);
return LibERC20Transformer.TRANSFORMER_SUCCESS;
}
}

View File

@ -45,7 +45,6 @@ contract TestFillQuoteTransformerHost is
this.rawExecuteTransform(
transformer,
IERC20Transformer.TransformContext({
callDataHash: bytes32(0),
sender: sender,
taker: taker,
data: data

View File

@ -34,9 +34,7 @@ contract TestMetaTransactionsTransformERC20Feature is
IERC20TokenV06 outputToken,
uint256 inputTokenAmount,
uint256 minOutputTokenAmount,
Transformation[] transformations,
bytes32 callDataHash,
bytes callDataSignature
Transformation[] transformations
);
constructor() public TransformERC20Feature(0) {}
@ -103,9 +101,7 @@ contract TestMetaTransactionsTransformERC20Feature is
args.outputToken,
args.inputTokenAmount,
args.minOutputTokenAmount,
args.transformations,
args.callDataHash,
args.callDataSignature
args.transformations
);
return 1337;
}

View File

@ -39,7 +39,6 @@ contract TestMintTokenERC20Transformer is
event MintTransform(
address context,
address caller,
bytes32 callDataHash,
address sender,
address taker,
bytes data,
@ -56,7 +55,6 @@ contract TestMintTokenERC20Transformer is
emit MintTransform(
address(this),
msg.sender,
context.callDataHash,
context.sender,
context.taker,
context.data,

View File

@ -51,7 +51,6 @@ contract TestWethTransformerHost is
this.rawExecuteTransform(
transformer,
IERC20Transformer.TransformContext({
callDataHash: bytes32(0),
sender: msg.sender,
taker: msg.sender,
data: data

View File

@ -42,7 +42,7 @@
"config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,SignatureValidatorFeature,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FeeCollector|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOrderHash|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FeeCollector|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOrderHash|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
},
"repository": {
"type": "git",

View File

@ -31,7 +31,6 @@ export {
export { artifacts } from './artifacts';
export * from './migration';
export * from './nonce_utils';
export * from './signed_call_data';
export * from './signature_utils';
export * from './orders';
export * from './eip712_utils';

View File

@ -1,29 +0,0 @@
import { SignatureType } from '@0x/types';
import { hexUtils } from '@0x/utils';
import * as ethjs from 'ethereumjs-util';
/**
* Generate calldata with a signature appended.
*/
export function signCallData(callData: string, privateKey: string): string {
const prefix = ethjs.sha3('SignedCallDataSignature(bytes)').slice(0, 4);
return hexUtils.concat(callData, prefix, generateCallDataSignature(callData, privateKey));
}
/**
* Generate a signature for calldata.
*/
export function generateCallDataSignature(callData: string, privateKey: string): string {
return generateCallDataHashSignature(hexUtils.hash(callData), privateKey);
}
/**
* Generate a signature for calldata hash.
*/
export function generateCallDataHashSignature(callDataHash: string, privateKey: string): string {
const { r, s, v } = ethjs.ecsign(
ethjs.hashPersonalMessage(ethjs.toBuffer(callDataHash)),
ethjs.toBuffer(privateKey),
);
return hexUtils.concat(v, r, s, SignatureType.EthSign);
}

View File

@ -60,7 +60,6 @@ import * as LibProxyStorage from '../test/generated-artifacts/LibProxyStorage.js
import * as LibReentrancyGuardStorage from '../test/generated-artifacts/LibReentrancyGuardStorage.json';
import * as LibSignature from '../test/generated-artifacts/LibSignature.json';
import * as LibSignatureRichErrors from '../test/generated-artifacts/LibSignatureRichErrors.json';
import * as LibSignedCallData from '../test/generated-artifacts/LibSignedCallData.json';
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
import * as LibSimpleFunctionRegistryStorage from '../test/generated-artifacts/LibSimpleFunctionRegistryStorage.json';
import * as LibSpenderRichErrors from '../test/generated-artifacts/LibSpenderRichErrors.json';
@ -177,7 +176,6 @@ export const artifacts = {
UniswapFeature: UniswapFeature as ContractArtifact,
LibNativeOrder: LibNativeOrder as ContractArtifact,
LibSignature: LibSignature as ContractArtifact,
LibSignedCallData: LibSignedCallData as ContractArtifact,
FixinCommon: FixinCommon as ContractArtifact,
FixinEIP712: FixinEIP712 as ContractArtifact,
FixinProtocolFees: FixinProtocolFees as ContractArtifact,

View File

@ -12,7 +12,6 @@ import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/
import * as _ from 'lodash';
import { Signature } from '../../src/signature_utils';
import { generateCallDataSignature, signCallData } from '../../src/signed_call_data';
import { IZeroExContract, MetaTransactionsFeatureContract } from '../../src/wrappers';
import { artifacts } from '../artifacts';
import { abis } from '../utils/abis';
@ -26,7 +25,7 @@ import {
TestMintableERC20TokenContract,
} from '../wrappers';
const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
const { NULL_ADDRESS, ZERO_AMOUNT } = constants;
blockchainTests.resets('MetaTransactions feature', env => {
let owner: string;
@ -257,16 +256,14 @@ blockchainTests.resets('MetaTransactions feature', env => {
transformations: args.transformations,
sender: zeroEx.address,
value: mtx.value,
callDataHash: hexUtils.hash(mtx.callData),
taker: mtx.signer,
callDataSignature: NULL_BYTES,
},
],
TestMetaTransactionsTransformERC20FeatureEvents.TransformERC20Called,
);
});
it('can call `TransformERC20.transformERC20()` with signed calldata', async () => {
it('can call `TransformERC20.transformERC20()` with calldata', async () => {
const args = getRandomTransformERC20Args();
const callData = transformERC20Feature
.transformERC20(
@ -277,10 +274,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
args.transformations,
)
.getABIEncodedTransactionData();
const callDataSignerKey = hexUtils.random();
const callDataSignature = generateCallDataSignature(callData, callDataSignerKey);
const signedCallData = signCallData(callData, callDataSignerKey);
const mtx = getRandomMetaTransaction({ callData: signedCallData });
const mtx = getRandomMetaTransaction({ callData });
const signature = await signMetaTransactionAsync(mtx);
const callOpts = {
gasPrice: mtx.minGasPrice,
@ -300,9 +294,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
transformations: args.transformations,
sender: zeroEx.address,
value: mtx.value,
callDataHash: hexUtils.hash(callData),
taker: mtx.signer,
callDataSignature,
},
],
TestMetaTransactionsTransformERC20FeatureEvents.TransformERC20Called,
@ -386,8 +378,6 @@ blockchainTests.resets('MetaTransactions feature', env => {
inputTokenAmount: args.inputTokenAmount,
minOutputTokenAmount: args.minOutputTokenAmount,
transformations: args.transformations,
callDataHash: hexUtils.hash(mtx.callData),
callDataSignature: NULL_BYTES,
})
.getABIEncodedTransactionData();
return expect(tx).to.revertWith(

View File

@ -10,10 +10,8 @@ import {
} from '@0x/contracts-test-utils';
import { ETH_TOKEN_ADDRESS } from '@0x/order-utils';
import { AbiEncoder, hexUtils, OwnableRevertErrors, ZeroExRevertErrors } from '@0x/utils';
import { DecodedLogEntry } from 'ethereum-types';
import * as ethjs from 'ethereumjs-util';
import { generateCallDataHashSignature, signCallData } from '../../src/signed_call_data';
import { IZeroExContract, TransformERC20FeatureContract } from '../../src/wrappers';
import { artifacts } from '../artifacts';
import { abis } from '../utils/abis';
@ -23,15 +21,10 @@ import {
TestMintableERC20TokenContract,
TestMintTokenERC20TransformerContract,
TestMintTokenERC20TransformerEvents,
TestMintTokenERC20TransformerMintTransformEventArgs,
TestTransformERC20Contract,
TransformERC20FeatureEvents,
} from '../wrappers';
const { NULL_ADDRESS, NULL_BYTES, NULL_BYTES32 } = constants;
type MintTokenTransformerEvent = DecodedLogEntry<TestMintTokenERC20TransformerMintTransformEventArgs>;
blockchainTests.resets('TransformERC20 feature', env => {
const callDataSignerKey = hexUtils.random();
const callDataSigner = ethjs.bufferToHex(ethjs.privateToAddress(ethjs.toBuffer(callDataSignerKey)));
@ -236,7 +229,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
const minOutputTokenAmount = getRandomInteger(1, '1e18');
const outputTokenMintAmount = minOutputTokenAmount;
const callValue = getRandomInteger(1, '1e18');
const callDataHash = hexUtils.random();
const transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
@ -249,8 +241,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
verifyEventsFromLogs(
@ -272,7 +262,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
{
sender,
taker,
callDataHash: NULL_BYTES32,
context: wallet.address,
caller: zeroEx.address,
data: transformation.data,
@ -291,7 +280,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
const minOutputTokenAmount = getRandomInteger(1, '1e18');
const outputTokenMintAmount = minOutputTokenAmount;
const callValue = outputTokenMintAmount.times(2);
const callDataHash = hexUtils.random();
const transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
@ -306,8 +294,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
verifyEventsFromLogs(
@ -329,7 +315,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
{
taker,
sender,
callDataHash: NULL_BYTES32,
context: wallet.address,
caller: zeroEx.address,
data: transformation.data,
@ -353,7 +338,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
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,
@ -366,8 +350,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
verifyEventsFromLogs(
@ -389,7 +371,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
{
sender,
taker,
callDataHash: NULL_BYTES32,
context: wallet.address,
caller: zeroEx.address,
data: transformation.data,
@ -412,13 +393,11 @@ blockchainTests.resets('TransformERC20 feature', env => {
const callValue = getRandomInteger(1, '1e18');
const tx = feature
._transformERC20({
callDataHash: hexUtils.random(),
taker,
inputToken: inputToken.address,
outputToken: outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
callDataSignature: NULL_BYTES,
transformations: [
createMintTokenTransformation({
outputTokenMintAmount,
@ -446,13 +425,11 @@ blockchainTests.resets('TransformERC20 feature', env => {
const callValue = getRandomInteger(1, '1e18');
const tx = feature
._transformERC20({
callDataHash: hexUtils.random(),
taker,
inputToken: inputToken.address,
outputToken: outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
callDataSignature: NULL_BYTES,
transformations: [
createMintTokenTransformation({
outputTokenFeeAmount,
@ -477,7 +454,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
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({
@ -497,8 +473,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount,
minOutputTokenAmount,
transformations,
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
verifyEventsFromLogs(
@ -507,7 +481,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
{
sender,
taker,
callDataHash: NULL_BYTES32,
context: wallet.address,
caller: zeroEx.address,
data: transformations[0].data,
@ -517,7 +490,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
{
sender,
taker,
callDataHash: NULL_BYTES32,
context: wallet.address,
caller: zeroEx.address,
data: transformations[1].data,
@ -537,7 +509,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
const inputTokenAmount = getRandomPortion(startingInputTokenBalance);
const minOutputTokenAmount = getRandomInteger(2, '1e18');
const callValue = getRandomInteger(1, '1e18');
const callDataHash = hexUtils.random();
const transformations = [createMintTokenTransformation({ deploymentNonce: 1337 })];
const tx = feature
._transformERC20({
@ -547,8 +518,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount,
minOutputTokenAmount,
transformations,
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
return expect(tx).to.revertWith(
@ -560,103 +529,12 @@ blockchainTests.resets('TransformERC20 feature', env => {
);
});
it('passes the calldata hash to transformer with proper signature', 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({
taker,
inputToken: inputToken.address,
outputToken: outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: generateCallDataHashSignature(callDataHash, callDataSignerKey),
})
.awaitTransactionSuccessAsync({ value: callValue });
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(callDataHash);
});
it('passes empty calldata hash to transformer with improper signature', 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({
taker,
inputToken: inputToken.address,
outputToken: outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: generateCallDataHashSignature(callDataHash, hexUtils.random()),
})
.awaitTransactionSuccessAsync({ value: callValue });
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(NULL_BYTES32);
});
it('passes empty calldata hash to transformer with no signature', 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({
taker,
inputToken: inputToken.address,
outputToken: outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(NULL_BYTES32);
});
it('can sell entire taker balance', async () => {
const startingInputTokenBalance = getRandomInteger(0, '100e18');
await inputToken.mint(taker, startingInputTokenBalance).awaitTransactionSuccessAsync();
const minOutputTokenAmount = getRandomInteger(1, '1e18');
const outputTokenMintAmount = minOutputTokenAmount;
const callValue = getRandomInteger(1, '1e18');
const callDataHash = hexUtils.random();
const transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: startingInputTokenBalance,
@ -669,8 +547,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount: MAX_UINT256,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: callValue });
verifyEventsFromLogs(
@ -693,7 +569,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
await inputToken.mint(taker, ethAttchedAmount).awaitTransactionSuccessAsync();
const minOutputTokenAmount = getRandomInteger(1, '1e18');
const outputTokenMintAmount = minOutputTokenAmount;
const callDataHash = hexUtils.random();
const transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenAddress: ETH_TOKEN_ADDRESS,
@ -707,8 +582,6 @@ blockchainTests.resets('TransformERC20 feature', env => {
inputTokenAmount: MAX_UINT256,
minOutputTokenAmount,
transformations: [transformation],
callDataHash,
callDataSignature: NULL_BYTES,
})
.awaitTransactionSuccessAsync({ value: ethAttchedAmount });
verifyEventsFromLogs(
@ -726,164 +599,5 @@ blockchainTests.resets('TransformERC20 feature', env => {
);
});
});
describe('transformERC20()', () => {
it('passes the calldata hash to transformer with properly signed calldata', 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 transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
});
const bakedCall = feature.transformERC20(
inputToken.address,
outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
[transformation],
);
const callData = bakedCall.getABIEncodedTransactionData();
const signedCallData = signCallData(callData, callDataSignerKey);
const receipt = await bakedCall.awaitTransactionSuccessAsync({
from: taker,
value: callValue,
data: signedCallData,
});
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(hexUtils.hash(callData));
});
it('passes the calldata hash to transformer when no quote signer configured', 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 transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
});
const bakedCall = feature.transformERC20(
inputToken.address,
outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
[transformation],
);
const callData = bakedCall.getABIEncodedTransactionData();
await feature.setQuoteSigner(NULL_ADDRESS).awaitTransactionSuccessAsync({ from: owner });
const receipt = await bakedCall.awaitTransactionSuccessAsync({
from: taker,
value: callValue,
data: callData,
});
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(hexUtils.hash(callData));
});
it('passes empty calldata hash to transformer with improperly signed calldata', 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 transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
});
const bakedCall = feature.transformERC20(
inputToken.address,
outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
[transformation],
);
const callData = bakedCall.getABIEncodedTransactionData();
const signedCallData = signCallData(callData, hexUtils.random());
const receipt = await bakedCall.awaitTransactionSuccessAsync({
from: taker,
value: callValue,
data: signedCallData,
});
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(NULL_BYTES32);
});
it('passes empty calldata hash to transformer with unsigned calldata', 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 transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
});
const bakedCall = feature.transformERC20(
inputToken.address,
outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
[transformation],
);
const callData = bakedCall.getABIEncodedTransactionData();
const receipt = await bakedCall.awaitTransactionSuccessAsync({
from: taker,
value: callValue,
data: callData,
});
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(NULL_BYTES32);
});
it('passes empty calldata hash to transformer with calldata with malformed signature', 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 transformation = createMintTokenTransformation({
outputTokenMintAmount,
inputTokenBurnAmunt: inputTokenAmount,
});
const bakedCall = feature.transformERC20(
inputToken.address,
outputToken.address,
inputTokenAmount,
minOutputTokenAmount,
[transformation],
);
const callData = bakedCall.getABIEncodedTransactionData();
const signedCallData = hexUtils.concat(
hexUtils.slice(signCallData(callData, hexUtils.random()), 0, -1),
127,
);
const receipt = await bakedCall.awaitTransactionSuccessAsync({
from: taker,
value: callValue,
data: signedCallData,
});
const { callDataHash: actualCallDataHash } = (receipt.logs[0] as MintTokenTransformerEvent).args;
expect(actualCallDataHash).to.eq(NULL_BYTES32);
});
});
});
});

View File

@ -1,6 +1,6 @@
import { blockchainTests, constants, expect, getRandomInteger, randomAddress } from '@0x/contracts-test-utils';
import { encodeAffiliateFeeTransformerData, ETH_TOKEN_ADDRESS } from '@0x/order-utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
@ -88,7 +88,6 @@ blockchainTests.resets('AffiliateFeeTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
sender: randomAddress(),
taker: randomAddress(),
})
@ -119,7 +118,6 @@ blockchainTests.resets('AffiliateFeeTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
sender: randomAddress(),
taker: randomAddress(),
})
@ -150,7 +148,6 @@ blockchainTests.resets('AffiliateFeeTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
sender: randomAddress(),
taker: randomAddress(),
})

View File

@ -1,6 +1,6 @@
import { blockchainTests, constants, expect, getRandomInteger, randomAddress } from '@0x/contracts-test-utils';
import { encodePayTakerTransformerData, ETH_TOKEN_ADDRESS } from '@0x/order-utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
@ -80,7 +80,6 @@ blockchainTests.resets('PayTakerTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
taker,
sender: randomAddress(),
})
@ -103,7 +102,6 @@ blockchainTests.resets('PayTakerTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
taker,
sender: randomAddress(),
})
@ -126,7 +124,6 @@ blockchainTests.resets('PayTakerTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
taker,
sender: randomAddress(),
})
@ -149,7 +146,6 @@ blockchainTests.resets('PayTakerTransformer', env => {
await host
.rawExecuteTransform(transformer.address, {
data,
callDataHash: hexUtils.random(),
taker,
sender: randomAddress(),
})

View File

@ -58,7 +58,6 @@ export * from '../test/generated-wrappers/lib_proxy_storage';
export * from '../test/generated-wrappers/lib_reentrancy_guard_storage';
export * from '../test/generated-wrappers/lib_signature';
export * from '../test/generated-wrappers/lib_signature_rich_errors';
export * from '../test/generated-wrappers/lib_signed_call_data';
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_spender_rich_errors';

View File

@ -85,7 +85,6 @@
"test/generated-artifacts/LibReentrancyGuardStorage.json",
"test/generated-artifacts/LibSignature.json",
"test/generated-artifacts/LibSignatureRichErrors.json",
"test/generated-artifacts/LibSignedCallData.json",
"test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json",
"test/generated-artifacts/LibSimpleFunctionRegistryStorage.json",
"test/generated-artifacts/LibSpenderRichErrors.json",