limit order metatransactions (#44)
This commit is contained in:
parent
5306cc03e9
commit
e2ee3414ea
@ -25,6 +25,10 @@
|
||||
{
|
||||
"note": "Convert metatransactions to use `LibSignature`",
|
||||
"pr": 31
|
||||
},
|
||||
{
|
||||
"note": "Add metatransaction support for limit orders",
|
||||
"pr": 44
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -35,6 +35,7 @@ import "./ITransformERC20Feature.sol";
|
||||
import "./libs/LibSignature.sol";
|
||||
import "./ISignatureValidatorFeature.sol";
|
||||
import "./IFeature.sol";
|
||||
import "./INativeOrdersFeature.sol";
|
||||
|
||||
/// @dev MetaTransactions feature.
|
||||
contract MetaTransactionsFeature is
|
||||
@ -48,7 +49,6 @@ contract MetaTransactionsFeature is
|
||||
using LibBytesV06 for bytes;
|
||||
using LibRichErrorsV06 for bytes;
|
||||
|
||||
|
||||
/// @dev Describes the state of a meta transaction.
|
||||
struct ExecuteState {
|
||||
// Sender of the meta-transaction.
|
||||
@ -292,6 +292,10 @@ contract MetaTransactionsFeature is
|
||||
state.selector = state.mtx.callData.readBytes4(0);
|
||||
if (state.selector == ITransformERC20Feature.transformERC20.selector) {
|
||||
returnResult = _executeTransformERC20Call(state);
|
||||
} else if (state.selector == INativeOrdersFeature.fillLimitOrder.selector) {
|
||||
returnResult = _executeFillLimitOrderCall(state);
|
||||
} else if (state.selector == INativeOrdersFeature.fillRfqOrder.selector) {
|
||||
returnResult = _executeFillRfqOrderCall(state);
|
||||
} else {
|
||||
LibMetaTransactionsRichErrors
|
||||
.MetaTransactionUnsupportedFunctionError(state.hash, state.selector)
|
||||
@ -453,6 +457,88 @@ contract MetaTransactionsFeature is
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Extract arguments from call data by copying everything after the
|
||||
/// 4-byte selector into a new byte array.
|
||||
/// @param callData The call data from which arguments are to be extracted.
|
||||
/// @return args The extracted arguments as a byte array.
|
||||
function _extractArgumentsFromCallData(
|
||||
bytes memory callData
|
||||
)
|
||||
private
|
||||
pure
|
||||
returns (bytes memory args)
|
||||
{
|
||||
args = new bytes(callData.length - 4);
|
||||
uint256 fromMem;
|
||||
uint256 toMem;
|
||||
|
||||
assembly {
|
||||
fromMem := add(callData, 36) // skip length and 4-byte selector
|
||||
toMem := add(args, 32) // write after length prefix
|
||||
}
|
||||
|
||||
LibBytesV06.memCopy(toMem, fromMem, args.length);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/// @dev Execute a `INativeOrdersFeature.fillLimitOrder()` meta-transaction call
|
||||
/// by decoding the call args and translating the call to the internal
|
||||
/// `INativeOrdersFeature._fillLimitOrder()` variant, where we can override
|
||||
/// the taker address.
|
||||
function _executeFillLimitOrderCall(ExecuteState memory state)
|
||||
private
|
||||
returns (bytes memory returnResult)
|
||||
{
|
||||
LibNativeOrder.LimitOrder memory order;
|
||||
LibSignature.Signature memory signature;
|
||||
uint128 takerTokenFillAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(order, signature, takerTokenFillAmount) = abi.decode(args, (LibNativeOrder.LimitOrder, LibSignature.Signature, uint128));
|
||||
|
||||
return _callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
INativeOrdersFeature._fillLimitOrder.selector,
|
||||
order,
|
||||
signature,
|
||||
takerTokenFillAmount,
|
||||
state.mtx.signer, // taker is mtx signer
|
||||
msg.sender
|
||||
),
|
||||
state.mtx.value
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Execute a `INativeOrdersFeature.fillRfqOrder()` meta-transaction call
|
||||
/// by decoding the call args and translating the call to the internal
|
||||
/// `INativeOrdersFeature._fillRfqOrder()` variant, where we can overrideunimpleme
|
||||
/// the taker address.
|
||||
function _executeFillRfqOrderCall(ExecuteState memory state)
|
||||
private
|
||||
returns (bytes memory returnResult)
|
||||
{
|
||||
LibNativeOrder.RfqOrder memory order;
|
||||
LibSignature.Signature memory signature;
|
||||
uint128 takerTokenFillAmount;
|
||||
|
||||
bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
|
||||
(order, signature, takerTokenFillAmount) = abi.decode(args, (LibNativeOrder.RfqOrder, LibSignature.Signature, uint128));
|
||||
|
||||
return _callSelf(
|
||||
state.hash,
|
||||
abi.encodeWithSelector(
|
||||
INativeOrdersFeature._fillRfqOrder.selector,
|
||||
order,
|
||||
signature,
|
||||
takerTokenFillAmount,
|
||||
state.mtx.signer // taker is mtx signer
|
||||
),
|
||||
state.mtx.value
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Make an arbitrary internal, meta-transaction call.
|
||||
/// Warning: Do not let unadulterated `callData` into this function.
|
||||
function _callSelf(bytes32 hash, bytes memory callData, uint256 value)
|
||||
|
@ -319,6 +319,7 @@ contract NativeOrdersFeature is
|
||||
address sender
|
||||
)
|
||||
public
|
||||
virtual
|
||||
override
|
||||
payable
|
||||
onlySelf
|
||||
@ -355,6 +356,7 @@ contract NativeOrdersFeature is
|
||||
address taker
|
||||
)
|
||||
public
|
||||
virtual
|
||||
override
|
||||
payable
|
||||
onlySelf
|
||||
|
@ -38,7 +38,7 @@ library LibSignature {
|
||||
/// The valid range is given by fig (283) of the yellow paper.
|
||||
uint256 private constant ECDSA_SIGNATURE_S_LIMIT = ECDSA_SIGNATURE_R_LIMIT / 2 + 1;
|
||||
|
||||
/// @dev Allowed signature types.
|
||||
/// @dev Allowed signature types.
|
||||
enum SignatureType {
|
||||
ILLEGAL,
|
||||
INVALID,
|
||||
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
|
||||
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/NativeOrdersFeature.sol";
|
||||
import "../src/features/IMetaTransactionsFeature.sol";
|
||||
|
||||
|
||||
contract TestMetaTransactionsNativeOrdersFeature is
|
||||
NativeOrdersFeature
|
||||
{
|
||||
constructor(
|
||||
)
|
||||
public
|
||||
NativeOrdersFeature(address(0), IEtherTokenV06(0), IStaking(0), 0, bytes32(0))
|
||||
{
|
||||
}
|
||||
|
||||
event FillLimitOrderCalled(
|
||||
LibNativeOrder.LimitOrder order,
|
||||
LibSignature.SignatureType signatureType,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s,
|
||||
uint128 takerTokenFillAmount,
|
||||
address taker,
|
||||
address sender
|
||||
);
|
||||
|
||||
function _fillLimitOrder(
|
||||
LibNativeOrder.LimitOrder memory order,
|
||||
LibSignature.Signature memory signature,
|
||||
uint128 takerTokenFillAmount,
|
||||
address taker,
|
||||
address sender
|
||||
)
|
||||
public
|
||||
override
|
||||
payable
|
||||
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
|
||||
{
|
||||
emit FillLimitOrderCalled(
|
||||
order,
|
||||
signature.signatureType,
|
||||
signature.v,
|
||||
signature.r,
|
||||
signature.s,
|
||||
takerTokenFillAmount,
|
||||
taker,
|
||||
sender
|
||||
);
|
||||
return (0, 1337);
|
||||
}
|
||||
|
||||
event FillRfqOrderCalled(
|
||||
LibNativeOrder.RfqOrder order,
|
||||
LibSignature.SignatureType signatureType,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s,
|
||||
uint128 takerTokenFillAmount,
|
||||
address taker
|
||||
);
|
||||
|
||||
function _fillRfqOrder(
|
||||
LibNativeOrder.RfqOrder memory order,
|
||||
LibSignature.Signature memory signature,
|
||||
uint128 takerTokenFillAmount,
|
||||
address taker
|
||||
)
|
||||
public
|
||||
override
|
||||
payable
|
||||
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
|
||||
{
|
||||
emit FillRfqOrderCalled(
|
||||
order,
|
||||
signature.signatureType,
|
||||
signature.v,
|
||||
signature.r,
|
||||
signature.s,
|
||||
takerTokenFillAmount,
|
||||
taker
|
||||
);
|
||||
return (0, 1337);
|
||||
}
|
||||
}
|
@ -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|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|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|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|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -104,6 +104,7 @@ import * as TestInitialMigration from '../test/generated-artifacts/TestInitialMi
|
||||
import * as TestLibNativeOrder from '../test/generated-artifacts/TestLibNativeOrder.json';
|
||||
import * as TestLibSignature from '../test/generated-artifacts/TestLibSignature.json';
|
||||
import * as TestLiquidityProvider from '../test/generated-artifacts/TestLiquidityProvider.json';
|
||||
import * as TestMetaTransactionsNativeOrdersFeature from '../test/generated-artifacts/TestMetaTransactionsNativeOrdersFeature.json';
|
||||
import * as TestMetaTransactionsTransformERC20Feature from '../test/generated-artifacts/TestMetaTransactionsTransformERC20Feature.json';
|
||||
import * as TestMigrator from '../test/generated-artifacts/TestMigrator.json';
|
||||
import * as TestMintableERC20Token from '../test/generated-artifacts/TestMintableERC20Token.json';
|
||||
@ -237,6 +238,7 @@ export const artifacts = {
|
||||
TestLibNativeOrder: TestLibNativeOrder as ContractArtifact,
|
||||
TestLibSignature: TestLibSignature as ContractArtifact,
|
||||
TestLiquidityProvider: TestLiquidityProvider as ContractArtifact,
|
||||
TestMetaTransactionsNativeOrdersFeature: TestMetaTransactionsNativeOrdersFeature as ContractArtifact,
|
||||
TestMetaTransactionsTransformERC20Feature: TestMetaTransactionsTransformERC20Feature as ContractArtifact,
|
||||
TestMigrator: TestMigrator as ContractArtifact,
|
||||
TestMintTokenERC20Transformer: TestMintTokenERC20Transformer as ContractArtifact,
|
||||
|
@ -17,7 +17,10 @@ import { IZeroExContract, MetaTransactionsFeatureContract } from '../../src/wrap
|
||||
import { artifacts } from '../artifacts';
|
||||
import { abis } from '../utils/abis';
|
||||
import { fullMigrateAsync } from '../utils/migration';
|
||||
import { getRandomLimitOrder, getRandomRfqOrder } from '../utils/orders';
|
||||
import {
|
||||
TestMetaTransactionsNativeOrdersFeatureContract,
|
||||
TestMetaTransactionsNativeOrdersFeatureEvents,
|
||||
TestMetaTransactionsTransformERC20FeatureContract,
|
||||
TestMetaTransactionsTransformERC20FeatureEvents,
|
||||
TestMintableERC20TokenContract,
|
||||
@ -27,12 +30,14 @@ const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
|
||||
|
||||
blockchainTests.resets('MetaTransactions feature', env => {
|
||||
let owner: string;
|
||||
let maker: string;
|
||||
let sender: string;
|
||||
let signers: string[];
|
||||
let zeroEx: IZeroExContract;
|
||||
let feature: MetaTransactionsFeatureContract;
|
||||
let feeToken: TestMintableERC20TokenContract;
|
||||
let transformERC20Feature: TestMetaTransactionsTransformERC20FeatureContract;
|
||||
let nativeOrdersFeature: TestMetaTransactionsNativeOrdersFeatureContract;
|
||||
|
||||
const MAX_FEE_AMOUNT = new BigNumber('1e18');
|
||||
const TRANSFORM_ERC20_FAILING_VALUE = new BigNumber(666);
|
||||
@ -41,15 +46,22 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
const REENTRANCY_FLAG_MTX = 0x1;
|
||||
|
||||
before(async () => {
|
||||
[owner, sender, ...signers] = await env.getAccountAddressesAsync();
|
||||
[owner, maker, sender, ...signers] = await env.getAccountAddressesAsync();
|
||||
transformERC20Feature = await TestMetaTransactionsTransformERC20FeatureContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMetaTransactionsTransformERC20Feature,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
{},
|
||||
);
|
||||
nativeOrdersFeature = await TestMetaTransactionsNativeOrdersFeatureContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMetaTransactionsNativeOrdersFeature,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
{},
|
||||
);
|
||||
zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, {
|
||||
transformERC20: transformERC20Feature.address,
|
||||
nativeOrders: nativeOrdersFeature.address,
|
||||
});
|
||||
feature = new MetaTransactionsFeatureContract(
|
||||
zeroEx.address,
|
||||
@ -141,9 +153,77 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
};
|
||||
}
|
||||
|
||||
const RAW_SUCCESS_RESULT = hexUtils.leftPad(1337);
|
||||
const RAW_TRANSFORM_SUCCESS_RESULT = hexUtils.leftPad(1337);
|
||||
const RAW_ORDER_SUCCESS_RESULT = hexUtils.leftPad(1337, 64);
|
||||
|
||||
describe('executeMetaTransaction()', () => {
|
||||
it('can call NativeOrders.fillLimitOrder()', async () => {
|
||||
const order = getRandomLimitOrder({ maker });
|
||||
const fillAmount = new BigNumber(23456);
|
||||
const sig = await order.getSignatureWithProviderAsync(env.provider);
|
||||
const mtx = getRandomMetaTransaction({
|
||||
callData: nativeOrdersFeature.fillLimitOrder(order, sig, fillAmount).getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
};
|
||||
const rawResult = await feature.executeMetaTransaction(mtx, signature).callAsync(callOpts);
|
||||
expect(rawResult).to.eq(RAW_ORDER_SUCCESS_RESULT);
|
||||
const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
||||
|
||||
verifyEventsFromLogs(
|
||||
receipt.logs,
|
||||
[
|
||||
{
|
||||
order: _.omit(order, ['verifyingContract', 'chainId']),
|
||||
sender: mtx.sender,
|
||||
taker: mtx.signer,
|
||||
takerTokenFillAmount: fillAmount,
|
||||
signatureType: sig.signatureType,
|
||||
v: sig.v,
|
||||
r: sig.r,
|
||||
s: sig.s,
|
||||
},
|
||||
],
|
||||
TestMetaTransactionsNativeOrdersFeatureEvents.FillLimitOrderCalled,
|
||||
);
|
||||
});
|
||||
|
||||
it('can call NativeOrders.fillRfqOrder()', async () => {
|
||||
const order = getRandomRfqOrder({ maker });
|
||||
const sig = await order.getSignatureWithProviderAsync(env.provider);
|
||||
const fillAmount = new BigNumber(23456);
|
||||
const mtx = getRandomMetaTransaction({
|
||||
callData: nativeOrdersFeature.fillRfqOrder(order, sig, fillAmount).getABIEncodedTransactionData(),
|
||||
});
|
||||
const signature = await signMetaTransactionAsync(mtx);
|
||||
const callOpts = {
|
||||
gasPrice: mtx.minGasPrice,
|
||||
value: mtx.value,
|
||||
};
|
||||
const rawResult = await feature.executeMetaTransaction(mtx, signature).callAsync(callOpts);
|
||||
expect(rawResult).to.eq(RAW_ORDER_SUCCESS_RESULT);
|
||||
const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
||||
|
||||
verifyEventsFromLogs(
|
||||
receipt.logs,
|
||||
[
|
||||
{
|
||||
order: _.omit(order, ['verifyingContract', 'chainId']),
|
||||
taker: mtx.signer,
|
||||
takerTokenFillAmount: fillAmount,
|
||||
signatureType: sig.signatureType,
|
||||
v: sig.v,
|
||||
r: sig.r,
|
||||
s: sig.s,
|
||||
},
|
||||
],
|
||||
TestMetaTransactionsNativeOrdersFeatureEvents.FillRfqOrderCalled,
|
||||
);
|
||||
});
|
||||
|
||||
it('can call `TransformERC20.transformERC20()`', async () => {
|
||||
const args = getRandomTransformERC20Args();
|
||||
const mtx = getRandomMetaTransaction({
|
||||
@ -163,7 +243,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
value: mtx.value,
|
||||
};
|
||||
const rawResult = await feature.executeMetaTransaction(mtx, signature).callAsync(callOpts);
|
||||
expect(rawResult).to.eq(RAW_SUCCESS_RESULT);
|
||||
expect(rawResult).to.eq(RAW_TRANSFORM_SUCCESS_RESULT);
|
||||
const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
||||
verifyEventsFromLogs(
|
||||
receipt.logs,
|
||||
@ -206,7 +286,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
value: mtx.value,
|
||||
};
|
||||
const rawResult = await feature.executeMetaTransaction(mtx, signature).callAsync(callOpts);
|
||||
expect(rawResult).to.eq(RAW_SUCCESS_RESULT);
|
||||
expect(rawResult).to.eq(RAW_TRANSFORM_SUCCESS_RESULT);
|
||||
const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
||||
verifyEventsFromLogs(
|
||||
receipt.logs,
|
||||
@ -249,7 +329,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
from: randomAddress(),
|
||||
};
|
||||
const rawResult = await feature.executeMetaTransaction(mtx, signature).callAsync(callOpts);
|
||||
expect(rawResult).to.eq(RAW_SUCCESS_RESULT);
|
||||
expect(rawResult).to.eq(RAW_TRANSFORM_SUCCESS_RESULT);
|
||||
});
|
||||
|
||||
it('works without fee', async () => {
|
||||
@ -273,7 +353,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
value: mtx.value,
|
||||
};
|
||||
const rawResult = await feature.executeMetaTransaction(mtx, signature).callAsync(callOpts);
|
||||
expect(rawResult).to.eq(RAW_SUCCESS_RESULT);
|
||||
expect(rawResult).to.eq(RAW_TRANSFORM_SUCCESS_RESULT);
|
||||
});
|
||||
|
||||
it('fails if the translated call fails', async () => {
|
||||
@ -638,7 +718,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
||||
value: BigNumber.sum(...mtxs.map(mtx => mtx.value)),
|
||||
};
|
||||
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_TRANSFORM_SUCCESS_RESULT));
|
||||
});
|
||||
|
||||
it('cannot execute the same transaction twice', async () => {
|
||||
|
@ -102,6 +102,7 @@ export * from '../test/generated-wrappers/test_initial_migration';
|
||||
export * from '../test/generated-wrappers/test_lib_native_order';
|
||||
export * from '../test/generated-wrappers/test_lib_signature';
|
||||
export * from '../test/generated-wrappers/test_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/test_meta_transactions_native_orders_feature';
|
||||
export * from '../test/generated-wrappers/test_meta_transactions_transform_erc20_feature';
|
||||
export * from '../test/generated-wrappers/test_migrator';
|
||||
export * from '../test/generated-wrappers/test_mint_token_erc20_transformer';
|
||||
|
@ -129,6 +129,7 @@
|
||||
"test/generated-artifacts/TestLibNativeOrder.json",
|
||||
"test/generated-artifacts/TestLibSignature.json",
|
||||
"test/generated-artifacts/TestLiquidityProvider.json",
|
||||
"test/generated-artifacts/TestMetaTransactionsNativeOrdersFeature.json",
|
||||
"test/generated-artifacts/TestMetaTransactionsTransformERC20Feature.json",
|
||||
"test/generated-artifacts/TestMigrator.json",
|
||||
"test/generated-artifacts/TestMintTokenERC20Transformer.json",
|
||||
|
Loading…
x
Reference in New Issue
Block a user