Convert MetaTransactionsFeature to use the new LibSignature (#31)
This commit is contained in:
parent
85f5d32de2
commit
5306cc03e9
@ -6,6 +6,7 @@ import {
|
|||||||
artifacts as exchangeProxyArtifacts,
|
artifacts as exchangeProxyArtifacts,
|
||||||
IZeroExContract,
|
IZeroExContract,
|
||||||
LogMetadataTransformerContract,
|
LogMetadataTransformerContract,
|
||||||
|
Signature,
|
||||||
signCallData,
|
signCallData,
|
||||||
} from '@0x/contracts-zero-ex';
|
} from '@0x/contracts-zero-ex';
|
||||||
import { migrateOnceAsync } from '@0x/migrations';
|
import { migrateOnceAsync } from '@0x/migrations';
|
||||||
@ -25,6 +26,15 @@ 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, NULL_BYTES32, ZERO_AMOUNT } = constants;
|
||||||
|
|
||||||
|
function sigstruct(signature: string): Signature {
|
||||||
|
return {
|
||||||
|
v: parseInt(hexUtils.slice(signature, 0, 1), 16),
|
||||||
|
signatureType: parseInt(hexUtils.slice(signature, 65, 66), 16),
|
||||||
|
r: hexUtils.slice(signature, 1, 33),
|
||||||
|
s: hexUtils.slice(signature, 33, 65),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
||||||
const quoteSignerKey = hexUtils.random();
|
const quoteSignerKey = hexUtils.random();
|
||||||
const quoteSigner = hexUtils.toHex(ethjs.privateToAddress(ethjs.toBuffer(quoteSignerKey)));
|
const quoteSigner = hexUtils.toHex(ethjs.privateToAddress(ethjs.toBuffer(quoteSignerKey)));
|
||||||
@ -240,7 +250,7 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
|||||||
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee, 0);
|
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee, 0);
|
||||||
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
||||||
const receipt = await zeroEx
|
const receipt = await zeroEx
|
||||||
.executeMetaTransaction(mtx, mtx.signature)
|
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
|
||||||
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
||||||
const relayerEthRefund = relayerEthBalanceBefore
|
const relayerEthRefund = relayerEthBalanceBefore
|
||||||
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
||||||
@ -276,7 +286,7 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
|||||||
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee);
|
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee);
|
||||||
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
||||||
const receipt = await zeroEx
|
const receipt = await zeroEx
|
||||||
.executeMetaTransaction(mtx, mtx.signature)
|
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
|
||||||
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
||||||
const relayerEthRefund = relayerEthBalanceBefore
|
const relayerEthRefund = relayerEthBalanceBefore
|
||||||
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
||||||
@ -311,7 +321,7 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
|||||||
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee);
|
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee);
|
||||||
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
||||||
const receipt = await zeroEx
|
const receipt = await zeroEx
|
||||||
.executeMetaTransaction(mtx, mtx.signature)
|
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
|
||||||
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
||||||
const relayerEthRefund = relayerEthBalanceBefore
|
const relayerEthRefund = relayerEthBalanceBefore
|
||||||
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
||||||
@ -348,7 +358,7 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
|||||||
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee, 0);
|
const mtx = await createMetaTransactionAsync(signedSwapData, _protocolFee, 0);
|
||||||
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
||||||
const receipt = await zeroEx
|
const receipt = await zeroEx
|
||||||
.executeMetaTransaction(mtx, mtx.signature)
|
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
|
||||||
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
||||||
const relayerEthRefund = relayerEthBalanceBefore
|
const relayerEthRefund = relayerEthBalanceBefore
|
||||||
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
||||||
@ -385,7 +395,7 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
|||||||
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
const relayerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(relayer);
|
||||||
await zeroEx.setQuoteSigner(NULL_ADDRESS).awaitTransactionSuccessAsync({ from: owner });
|
await zeroEx.setQuoteSigner(NULL_ADDRESS).awaitTransactionSuccessAsync({ from: owner });
|
||||||
const receipt = await zeroEx
|
const receipt = await zeroEx
|
||||||
.executeMetaTransaction(mtx, mtx.signature)
|
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
|
||||||
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
||||||
const relayerEthRefund = relayerEthBalanceBefore
|
const relayerEthRefund = relayerEthBalanceBefore
|
||||||
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
.minus(await env.web3Wrapper.getBalanceInWeiAsync(relayer))
|
||||||
@ -419,7 +429,7 @@ blockchainTests.resets('exchange proxy - meta-transactions', env => {
|
|||||||
const _protocolFee = protocolFee.times(GAS_PRICE).times(swap.orders.length + 1); // Pay a little more fee than needed.
|
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 mtx = await createMetaTransactionAsync(callData, _protocolFee, 0);
|
||||||
const tx = zeroEx
|
const tx = zeroEx
|
||||||
.executeMetaTransaction(mtx, mtx.signature)
|
.executeMetaTransaction(mtx, sigstruct(mtx.signature))
|
||||||
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
.awaitTransactionSuccessAsync({ from: relayer, value: mtx.value, gasPrice: GAS_PRICE });
|
||||||
return expect(tx).to.revertWith(new ZeroExRevertErrors.MetaTransactions.MetaTransactionCallFailedError());
|
return expect(tx).to.revertWith(new ZeroExRevertErrors.MetaTransactions.MetaTransactionCallFailedError());
|
||||||
});
|
});
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add a gas limit to first `LibTokenSpender` and `UniswapFeature` transfer",
|
"note": "Add a gas limit to first `LibTokenSpender` and `UniswapFeature` transfer",
|
||||||
"pr": 38
|
"pr": 38
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Convert metatransactions to use `LibSignature`",
|
||||||
|
"pr": 31
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -20,11 +20,10 @@ pragma solidity ^0.6.5;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
import "./libs/LibSignature.sol";
|
||||||
|
|
||||||
/// @dev Meta-transactions feature.
|
/// @dev Meta-transactions feature.
|
||||||
interface IMetaTransactionsFeature {
|
interface IMetaTransactionsFeature {
|
||||||
|
|
||||||
/// @dev Describes an exchange proxy meta transaction.
|
/// @dev Describes an exchange proxy meta transaction.
|
||||||
struct MetaTransactionData {
|
struct MetaTransactionData {
|
||||||
// Signer of meta-transaction. On whose behalf to execute the MTX.
|
// Signer of meta-transaction. On whose behalf to execute the MTX.
|
||||||
@ -68,7 +67,7 @@ interface IMetaTransactionsFeature {
|
|||||||
/// @return returnResult 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
|
LibSignature.Signature calldata signature
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
payable
|
payable
|
||||||
@ -80,7 +79,7 @@ interface IMetaTransactionsFeature {
|
|||||||
/// @return returnResults The ABI-encoded results of the underlying calls.
|
/// @return returnResults The ABI-encoded results of the underlying calls.
|
||||||
function batchExecuteMetaTransactions(
|
function batchExecuteMetaTransactions(
|
||||||
MetaTransactionData[] calldata mtxs,
|
MetaTransactionData[] calldata mtxs,
|
||||||
bytes[] calldata signatures
|
LibSignature.Signature[] calldata signatures
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
payable
|
payable
|
||||||
@ -88,14 +87,14 @@ interface IMetaTransactionsFeature {
|
|||||||
|
|
||||||
/// @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 returnResult 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 memory mtx,
|
||||||
bytes calldata signature
|
LibSignature.Signature memory signature
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
payable
|
payable
|
||||||
|
@ -32,6 +32,7 @@ import "../storage/LibMetaTransactionsStorage.sol";
|
|||||||
import "./libs/LibSignedCallData.sol";
|
import "./libs/LibSignedCallData.sol";
|
||||||
import "./IMetaTransactionsFeature.sol";
|
import "./IMetaTransactionsFeature.sol";
|
||||||
import "./ITransformERC20Feature.sol";
|
import "./ITransformERC20Feature.sol";
|
||||||
|
import "./libs/LibSignature.sol";
|
||||||
import "./ISignatureValidatorFeature.sol";
|
import "./ISignatureValidatorFeature.sol";
|
||||||
import "./IFeature.sol";
|
import "./IFeature.sol";
|
||||||
|
|
||||||
@ -47,8 +48,8 @@ contract MetaTransactionsFeature is
|
|||||||
using LibBytesV06 for bytes;
|
using LibBytesV06 for bytes;
|
||||||
using LibRichErrorsV06 for bytes;
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
/// @dev Intermediate state vars used by `_executeMetaTransactionPrivate()`
|
|
||||||
/// to avoid stack overflows.
|
/// @dev Describes the state of a meta transaction.
|
||||||
struct ExecuteState {
|
struct ExecuteState {
|
||||||
// Sender of the meta-transaction.
|
// Sender of the meta-transaction.
|
||||||
address sender;
|
address sender;
|
||||||
@ -57,7 +58,7 @@ contract MetaTransactionsFeature is
|
|||||||
// The meta-transaction data.
|
// The meta-transaction data.
|
||||||
MetaTransactionData mtx;
|
MetaTransactionData mtx;
|
||||||
// The meta-transaction signature (by `mtx.signer`).
|
// The meta-transaction signature (by `mtx.signer`).
|
||||||
bytes signature;
|
LibSignature.Signature signature;
|
||||||
// The selector of the function being called.
|
// The selector of the function being called.
|
||||||
bytes4 selector;
|
bytes4 selector;
|
||||||
// The ETH balance of this contract before performing the call.
|
// The ETH balance of this contract before performing the call.
|
||||||
@ -136,7 +137,7 @@ contract MetaTransactionsFeature is
|
|||||||
/// @return returnResult 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
|
LibSignature.Signature memory signature
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
payable
|
payable
|
||||||
@ -145,11 +146,13 @@ contract MetaTransactionsFeature is
|
|||||||
refundsAttachedEth
|
refundsAttachedEth
|
||||||
returns (bytes memory returnResult)
|
returns (bytes memory returnResult)
|
||||||
{
|
{
|
||||||
returnResult = _executeMetaTransactionPrivate(
|
ExecuteState memory state;
|
||||||
msg.sender,
|
state.sender = msg.sender;
|
||||||
mtx,
|
state.mtx = mtx;
|
||||||
signature
|
state.hash = getMetaTransactionHash(mtx);
|
||||||
);
|
state.signature = signature;
|
||||||
|
|
||||||
|
returnResult = _executeMetaTransactionPrivate(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Execute multiple meta-transactions.
|
/// @dev Execute multiple meta-transactions.
|
||||||
@ -158,7 +161,7 @@ contract MetaTransactionsFeature is
|
|||||||
/// @return returnResults The ABI-encoded results of the underlying calls.
|
/// @return returnResults The ABI-encoded results of the underlying calls.
|
||||||
function batchExecuteMetaTransactions(
|
function batchExecuteMetaTransactions(
|
||||||
MetaTransactionData[] memory mtxs,
|
MetaTransactionData[] memory mtxs,
|
||||||
bytes[] memory signatures
|
LibSignature.Signature[] memory signatures
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
payable
|
payable
|
||||||
@ -175,11 +178,13 @@ contract MetaTransactionsFeature is
|
|||||||
}
|
}
|
||||||
returnResults = 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) {
|
||||||
returnResults[i] = _executeMetaTransactionPrivate(
|
ExecuteState memory state;
|
||||||
msg.sender,
|
state.sender = msg.sender;
|
||||||
mtxs[i],
|
state.mtx = mtxs[i];
|
||||||
signatures[i]
|
state.hash = getMetaTransactionHash(mtxs[i]);
|
||||||
);
|
state.signature = signatures[i];
|
||||||
|
|
||||||
|
returnResults[i] = _executeMetaTransactionPrivate(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +197,7 @@ contract MetaTransactionsFeature is
|
|||||||
function _executeMetaTransaction(
|
function _executeMetaTransaction(
|
||||||
address sender,
|
address sender,
|
||||||
MetaTransactionData memory mtx,
|
MetaTransactionData memory mtx,
|
||||||
bytes memory signature
|
LibSignature.Signature memory signature
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
payable
|
payable
|
||||||
@ -200,7 +205,13 @@ contract MetaTransactionsFeature is
|
|||||||
onlySelf
|
onlySelf
|
||||||
returns (bytes memory returnResult)
|
returns (bytes memory returnResult)
|
||||||
{
|
{
|
||||||
return _executeMetaTransactionPrivate(sender, mtx, signature);
|
ExecuteState memory state;
|
||||||
|
state.sender = sender;
|
||||||
|
state.mtx = mtx;
|
||||||
|
state.hash = getMetaTransactionHash(mtx);
|
||||||
|
state.signature = signature;
|
||||||
|
|
||||||
|
return _executeMetaTransactionPrivate(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Get the block at which a meta-transaction has been executed.
|
/// @dev Get the block at which a meta-transaction has been executed.
|
||||||
@ -252,24 +263,13 @@ contract MetaTransactionsFeature is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Execute a meta-transaction by `sender`. Low-level, hidden variant.
|
/// @dev Execute a meta-transaction by `sender`. Low-level, hidden variant.
|
||||||
/// @param sender Who is executing the meta-transaction..
|
/// @param state The `ExecuteState` for this metatransaction, with `sender`,
|
||||||
/// @param mtx The meta-transaction.
|
/// `hash`, `mtx`, and `signature` fields filled.
|
||||||
/// @param signature The signature by `mtx.signer`.
|
|
||||||
/// @return returnResult The ABI-encoded result of the underlying call.
|
/// @return returnResult The ABI-encoded result of the underlying call.
|
||||||
function _executeMetaTransactionPrivate(
|
function _executeMetaTransactionPrivate(ExecuteState memory state)
|
||||||
address sender,
|
|
||||||
MetaTransactionData memory mtx,
|
|
||||||
bytes memory signature
|
|
||||||
)
|
|
||||||
private
|
private
|
||||||
returns (bytes memory returnResult)
|
returns (bytes memory returnResult)
|
||||||
{
|
{
|
||||||
ExecuteState memory state;
|
|
||||||
state.sender = sender;
|
|
||||||
state.hash = getMetaTransactionHash(mtx);
|
|
||||||
state.mtx = mtx;
|
|
||||||
state.signature = signature;
|
|
||||||
|
|
||||||
_validateMetaTransaction(state);
|
_validateMetaTransaction(state);
|
||||||
|
|
||||||
// Mark the transaction executed by storing the block at which it was executed.
|
// Mark the transaction executed by storing the block at which it was executed.
|
||||||
@ -279,17 +279,17 @@ contract MetaTransactionsFeature is
|
|||||||
.mtxHashToExecutedBlockNumber[state.hash] = block.number;
|
.mtxHashToExecutedBlockNumber[state.hash] = block.number;
|
||||||
|
|
||||||
// Pay the fee to the sender.
|
// Pay the fee to the sender.
|
||||||
if (mtx.feeAmount > 0) {
|
if (state.mtx.feeAmount > 0) {
|
||||||
_transferERC20Tokens(
|
_transferERC20Tokens(
|
||||||
mtx.feeToken,
|
state.mtx.feeToken,
|
||||||
mtx.signer,
|
state.mtx.signer,
|
||||||
sender,
|
state.sender,
|
||||||
mtx.feeAmount
|
state.mtx.feeAmount
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the call based on the selector.
|
// Execute the call based on the selector.
|
||||||
state.selector = mtx.callData.readBytes4(0);
|
state.selector = state.mtx.callData.readBytes4(0);
|
||||||
if (state.selector == ITransformERC20Feature.transformERC20.selector) {
|
if (state.selector == ITransformERC20Feature.transformERC20.selector) {
|
||||||
returnResult = _executeTransformERC20Call(state);
|
returnResult = _executeTransformERC20Call(state);
|
||||||
} else {
|
} else {
|
||||||
@ -300,8 +300,8 @@ contract MetaTransactionsFeature is
|
|||||||
emit MetaTransactionExecuted(
|
emit MetaTransactionExecuted(
|
||||||
state.hash,
|
state.hash,
|
||||||
state.selector,
|
state.selector,
|
||||||
mtx.signer,
|
state.mtx.signer,
|
||||||
mtx.sender
|
state.mtx.sender
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,18 +348,17 @@ contract MetaTransactionsFeature is
|
|||||||
state.mtx.value
|
state.mtx.value
|
||||||
).rrevert();
|
).rrevert();
|
||||||
}
|
}
|
||||||
// Must be signed by signer.
|
|
||||||
try
|
if (LibSignature.getSignerOfHash(state.hash, state.signature) !=
|
||||||
ISignatureValidatorFeature(address(this))
|
state.mtx.signer) {
|
||||||
.validateHashSignature(state.hash, state.mtx.signer, state.signature)
|
LibSignatureRichErrors.SignatureValidationError(
|
||||||
{}
|
LibSignatureRichErrors.SignatureValidationErrorCodes.WRONG_SIGNER,
|
||||||
catch (bytes memory err) {
|
state.hash,
|
||||||
LibMetaTransactionsRichErrors
|
state.mtx.signer,
|
||||||
.MetaTransactionInvalidSignatureError(
|
// TODO: Remove this field from SignatureValidationError
|
||||||
state.hash,
|
// when rich reverts are part of the protocol repo.
|
||||||
state.signature,
|
""
|
||||||
err
|
).rrevert();
|
||||||
).rrevert();
|
|
||||||
}
|
}
|
||||||
// Transaction must not have been already executed.
|
// Transaction must not have been already executed.
|
||||||
state.executedBlockNumber = LibMetaTransactionsStorage
|
state.executedBlockNumber = LibMetaTransactionsStorage
|
||||||
|
@ -52,6 +52,8 @@ contract TestMetaTransactionsTransformERC20Feature is
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg.value == 777) {
|
if (msg.value == 777) {
|
||||||
|
LibSignature.Signature memory signature;
|
||||||
|
|
||||||
// Try to reenter `executeMetaTransaction()`
|
// Try to reenter `executeMetaTransaction()`
|
||||||
IMetaTransactionsFeature(address(this)).executeMetaTransaction(
|
IMetaTransactionsFeature(address(this)).executeMetaTransaction(
|
||||||
IMetaTransactionsFeature.MetaTransactionData({
|
IMetaTransactionsFeature.MetaTransactionData({
|
||||||
@ -66,7 +68,7 @@ contract TestMetaTransactionsTransformERC20Feature is
|
|||||||
feeToken: IERC20TokenV06(0),
|
feeToken: IERC20TokenV06(0),
|
||||||
feeAmount: 0
|
feeAmount: 0
|
||||||
}),
|
}),
|
||||||
""
|
signature
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ contract TestMetaTransactionsTransformERC20Feature is
|
|||||||
// Try to reenter `batchExecuteMetaTransactions()`
|
// Try to reenter `batchExecuteMetaTransactions()`
|
||||||
IMetaTransactionsFeature.MetaTransactionData[] memory mtxs =
|
IMetaTransactionsFeature.MetaTransactionData[] memory mtxs =
|
||||||
new IMetaTransactionsFeature.MetaTransactionData[](1);
|
new IMetaTransactionsFeature.MetaTransactionData[](1);
|
||||||
bytes[] memory signatures = new bytes[](1);
|
LibSignature.Signature[] memory signatures = new LibSignature.Signature[](1);
|
||||||
mtxs[0] = IMetaTransactionsFeature.MetaTransactionData({
|
mtxs[0] = IMetaTransactionsFeature.MetaTransactionData({
|
||||||
signer: address(0),
|
signer: address(0),
|
||||||
sender: address(0),
|
sender: address(0),
|
||||||
@ -87,7 +89,6 @@ contract TestMetaTransactionsTransformERC20Feature is
|
|||||||
feeToken: IERC20TokenV06(0),
|
feeToken: IERC20TokenV06(0),
|
||||||
feeAmount: 0
|
feeAmount: 0
|
||||||
});
|
});
|
||||||
signatures[0] = "";
|
|
||||||
IMetaTransactionsFeature(address(this)).batchExecuteMetaTransactions(
|
IMetaTransactionsFeature(address(this)).batchExecuteMetaTransactions(
|
||||||
mtxs,
|
mtxs,
|
||||||
signatures
|
signatures
|
||||||
|
@ -11,6 +11,7 @@ import { ExchangeProxyMetaTransaction } from '@0x/types';
|
|||||||
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { Signature } from '../../src/signature_utils';
|
||||||
import { generateCallDataSignature, signCallData } from '../../src/signed_call_data';
|
import { generateCallDataSignature, signCallData } from '../../src/signed_call_data';
|
||||||
import { IZeroExContract, MetaTransactionsFeatureContract } from '../../src/wrappers';
|
import { IZeroExContract, MetaTransactionsFeatureContract } from '../../src/wrappers';
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
@ -71,6 +72,15 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function sigstruct(signature: string): Signature {
|
||||||
|
return {
|
||||||
|
v: parseInt(hexUtils.slice(signature, 0, 1), 16),
|
||||||
|
signatureType: parseInt(hexUtils.slice(signature, 65, 66), 16),
|
||||||
|
r: hexUtils.slice(signature, 1, 33),
|
||||||
|
s: hexUtils.slice(signature, 33, 65),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function getRandomMetaTransaction(
|
function getRandomMetaTransaction(
|
||||||
fields: Partial<ExchangeProxyMetaTransaction> = {},
|
fields: Partial<ExchangeProxyMetaTransaction> = {},
|
||||||
): ExchangeProxyMetaTransaction {
|
): ExchangeProxyMetaTransaction {
|
||||||
@ -93,11 +103,13 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function signMetaTransactionAsync(mtx: ExchangeProxyMetaTransaction, signer?: string): Promise<string> {
|
async function signMetaTransactionAsync(mtx: ExchangeProxyMetaTransaction, signer?: string): Promise<Signature> {
|
||||||
return signatureUtils.ecSignHashAsync(
|
return sigstruct(
|
||||||
env.provider,
|
await signatureUtils.ecSignHashAsync(
|
||||||
getExchangeProxyMetaTransactionHash(mtx),
|
env.provider,
|
||||||
signer || mtx.signer,
|
getExchangeProxyMetaTransactionHash(mtx),
|
||||||
|
signer || mtx.signer,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,15 +473,11 @@ blockchainTests.resets('MetaTransactions feature', env => {
|
|||||||
};
|
};
|
||||||
const tx = feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
const tx = feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
|
||||||
return expect(tx).to.revertWith(
|
return expect(tx).to.revertWith(
|
||||||
new ZeroExRevertErrors.MetaTransactions.MetaTransactionInvalidSignatureError(
|
new ZeroExRevertErrors.SignatureValidator.SignatureValidationError(
|
||||||
|
ZeroExRevertErrors.SignatureValidator.SignatureValidationErrorCodes.WrongSigner,
|
||||||
mtxHash,
|
mtxHash,
|
||||||
signature,
|
signers[0],
|
||||||
new ZeroExRevertErrors.SignatureValidator.SignatureValidationError(
|
'0x',
|
||||||
ZeroExRevertErrors.SignatureValidator.SignatureValidationErrorCodes.WrongSigner,
|
|
||||||
mtxHash,
|
|
||||||
signers[0],
|
|
||||||
signature,
|
|
||||||
).encode(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user