@0x/contracts-zero-ex: Rebase, returning nonces in transform().

This commit is contained in:
Lawrence Forman
2020-05-20 02:08:11 -04:00
committed by Lawrence Forman
parent 2ba3818b65
commit c610dd96f5
17 changed files with 182 additions and 44 deletions

View File

@@ -35,8 +35,6 @@ import "./LibERC20Transformer.sol";
contract FillQuoteTransformer is
IERC20Transformer
{
// solhint-disable indent,no-empty-blocks,no-unused-vars
/// @dev Transform data to ABI-encode and pass into `transform()`.
struct TransformData {
// The token being sold.
@@ -76,6 +74,8 @@ contract FillQuoteTransformer is
/// @dev The Exchange contract.
IExchange public immutable exchange;
/// @dev The nonce of the deployer when deploying this contract.
uint256 public immutable deploymentNonce;
/// @dev The ERC20Proxy address.
address public immutable erc20Proxy;
@@ -84,9 +84,13 @@ contract FillQuoteTransformer is
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
constructor(IExchange exchange_) public {
/// @dev Create this contract.
/// @param exchange_ The Exchange V3 instance.
/// @param deploymentNonce_ The nonce of the deployer when deploying this contract.
constructor(IExchange exchange_, uint256 deploymentNonce_) public {
exchange = exchange_;
erc20Proxy = exchange_.getAssetProxy(ERC20_ASSET_PROXY_ID);
deploymentNonce = deploymentNonce_;
}
/// @dev Sell this contract's entire balance of of `sellToken` in exchange
@@ -94,7 +98,9 @@ contract FillQuoteTransformer is
/// to this call. `buyToken` and excess ETH will be transferred back to the caller.
/// This function cannot be re-entered.
/// @param data_ ABI-encoded `TransformData`.
/// @return success `TRANSFORMER_SUCCESS` on success.
/// @return rlpDeploymentNonce RLP-encoded deployment nonce of the deployer
/// when this transformer was deployed. This is used to verify that
/// this transformer was deployed by a trusted contract.
function transform(
bytes32, // callDataHash,
address payable, // taker,
@@ -102,7 +108,7 @@ contract FillQuoteTransformer is
)
external
override
returns (bytes4 success)
returns (bytes memory rlpDeploymentNonce)
{
TransformData memory data = abi.decode(data_, (TransformData));
@@ -211,7 +217,7 @@ contract FillQuoteTransformer is
).rrevert();
}
}
return LibERC20Transformer.TRANSFORMER_SUCCESS;
return LibERC20Transformer.rlpEncodeNonce(deploymentNonce);
}
/// @dev Try to sell up to `sellAmount` from an order.

View File

@@ -70,4 +70,45 @@ library LibERC20Transformer {
{
return isTokenETH(token) ? owner.balance : token.balanceOf(owner);
}
/// @dev RLP-encode a 32-bit or less account nonce.
/// @param nonce A positive integer in the range 0 <= nonce < 2^32.
/// @return rlpNonce The RLP encoding.
function rlpEncodeNonce(uint256 nonce)
internal
pure
returns (bytes memory rlpNonce)
{
if (nonce == 0) {
rlpNonce = new bytes(1);
rlpNonce[0] = 0x80;
} else if (nonce < 0x80) {
rlpNonce = new bytes(1);
rlpNonce[0] = byte(uint8(nonce));
} else if (nonce <= 0xFF) {
rlpNonce = new bytes(2);
rlpNonce[0] = 0x81;
rlpNonce[1] = byte(uint8(nonce));
} else if (nonce <= 0xFFFF) {
rlpNonce = new bytes(3);
rlpNonce[0] = 0x82;
rlpNonce[1] = byte(uint8((nonce & 0xFF00) >> 8));
rlpNonce[2] = byte(uint8(nonce));
} else if (nonce <= 0xFFFFFF) {
rlpNonce = new bytes(4);
rlpNonce[0] = 0x83;
rlpNonce[1] = byte(uint8((nonce & 0xFF0000) >> 16));
rlpNonce[2] = byte(uint8((nonce & 0xFF00) >> 8));
rlpNonce[3] = byte(uint8(nonce));
} else if (nonce <= 0xFFFFFFFF) {
rlpNonce = new bytes(5);
rlpNonce[0] = 0x84;
rlpNonce[1] = byte(uint8((nonce & 0xFF000000) >> 24));
rlpNonce[2] = byte(uint8((nonce & 0xFF0000) >> 16));
rlpNonce[3] = byte(uint8((nonce & 0xFF00) >> 8));
rlpNonce[4] = byte(uint8(nonce));
} else {
revert("LibERC20Transformer/INVALID_ENCODE_NONCE");
}
}
}

View File

@@ -45,10 +45,21 @@ contract PayTakerTransformer is
using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06;
/// @dev The nonce of the deployer when deploying this contract.
uint256 public immutable deploymentNonce;
/// @dev Create this contract.
/// @param deploymentNonce_ The nonce of the deployer when deploying this contract.
constructor(uint256 deploymentNonce_) public {
deploymentNonce = deploymentNonce_;
}
/// @dev Forwards tokens to the taker.
/// @param taker The taker address (caller of `TransformERC20.transformERC20()`).
/// @param data_ ABI-encoded `TransformData`, indicating which tokens to transfer.
/// @return success `TRANSFORMER_SUCCESS` on success.
/// @return rlpDeploymentNonce RLP-encoded deployment nonce of the deployer
/// when this transformer was deployed. This is used to verify that
/// this transformer was deployed by a trusted contract.
function transform(
bytes32, // callDataHash,
address payable taker,
@@ -56,7 +67,7 @@ contract PayTakerTransformer is
)
external
override
returns (bytes4 success)
returns (bytes memory rlpDeploymentNonce)
{
TransformData memory data = abi.decode(data_, (TransformData));
@@ -72,6 +83,6 @@ contract PayTakerTransformer is
data.tokens[i].transformerTransfer(taker, amount);
}
}
return LibERC20Transformer.TRANSFORMER_SUCCESS;
return LibERC20Transformer.rlpEncodeNonce(deploymentNonce);
}
}

View File

@@ -40,24 +40,29 @@ contract WethTransformer is
uint256 amount;
}
// solhint-disable
/// @dev The WETH contract address.
IEtherTokenV06 public immutable weth;
// solhint-enable
/// @dev The nonce of the deployer when deploying this contract.
uint256 public immutable deploymentNonce;
using LibRichErrorsV06 for bytes;
using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06;
/// @dev Construct the transformer and store the WETH address in an immutable.
/// @dev Create this contract.
/// @param weth_ The weth token.
constructor(IEtherTokenV06 weth_) public {
/// @param deploymentNonce_ The nonce of the deployer when deploying this contract.
/// @dev Construct the transformer and store the WETH address in an immutable.
constructor(IEtherTokenV06 weth_, uint256 deploymentNonce_) public {
weth = weth_;
deploymentNonce = deploymentNonce_;
}
/// @dev Wraps and unwraps WETH.
/// @param data_ ABI-encoded `TransformData`, indicating which token to wrap/umwrap.
/// @return success `TRANSFORMER_SUCCESS` on success.
/// @return rlpDeploymentNonce RLP-encoded deployment nonce of the deployer
/// when this transformer was deployed. This is used to verify that
/// this transformer was deployed by a trusted contract.
function transform(
bytes32, // callDataHash,
address payable, // taker,
@@ -65,7 +70,7 @@ contract WethTransformer is
)
external
override
returns (bytes4 success)
returns (bytes memory rlpDeploymentNonce)
{
TransformData memory data = abi.decode(data_, (TransformData));
if (!data.token.isTokenETH() && data.token != weth) {
@@ -86,6 +91,6 @@ contract WethTransformer is
weth.withdraw(amount);
}
}
return LibERC20Transformer.TRANSFORMER_SUCCESS;
return LibERC20Transformer.rlpEncodeNonce(deploymentNonce);
}
}

View File

@@ -35,11 +35,12 @@ contract TestFillQuoteTransformerHost is
)
external
payable
returns (bytes memory rlpDeploymentNonce)
{
if (inputTokenAmount != 0) {
inputToken.mint(address(this), inputTokenAmount);
}
// Have to make this call externally because transformers aren't payable.
this.rawExecuteTransform(transformer, bytes32(0), msg.sender, data);
return this.rawExecuteTransform(transformer, bytes32(0), msg.sender, data);
}
}

View File

@@ -37,6 +37,7 @@ contract TestTransformerHost {
bytes calldata data
)
external
returns (bytes memory rlpDeploymentNonce)
{
(bool success, bytes memory resultData) =
address(transformer).delegatecall(abi.encodeWithSelector(
@@ -48,10 +49,7 @@ contract TestTransformerHost {
if (!success) {
resultData.rrevert();
}
require(
abi.decode(resultData, (bytes4)) == LibERC20Transformer.TRANSFORMER_SUCCESS,
"TestFillQuoteTransformerTaker/UNSUCCESSFUL_RESULT"
);
assembly { return(add(resultData, 32), mload(resultData)) }
}
// solhint-disable

View File

@@ -43,11 +43,12 @@ contract TestWethTransformerHost is
)
external
payable
returns (bytes memory rlpDeploymentNonce)
{
if (wethAmount != 0) {
_weth.deposit{value: wethAmount}();
}
// Have to make this call externally because transformers aren't payable.
this.rawExecuteTransform(transformer, bytes32(0), msg.sender, data);
return this.rawExecuteTransform(transformer, bytes32(0), msg.sender, data);
}
}

View File

@@ -40,7 +40,7 @@
"config": {
"publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AllowanceTarget|Bootstrap|FixinCommon|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Transformer|IFeature|IFlashWallet|IOwnable|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|Ownable|SimpleFunctionRegistry|TestCallTarget|TestFullMigration|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestZeroExFeature|TokenSpender|TransformERC20|ZeroEx).json"
"abis": "./test/generated-artifacts/@(AllowanceTarget|Bootstrap|FillQuoteTransformer|FixinCommon|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Transformer|IExchange|IFeature|IFlashWallet|IOwnable|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|Ownable|PayTakerTransformer|SimpleFunctionRegistry|TestCallTarget|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|WethTransformer|ZeroEx).json"
},
"repository": {
"type": "git",

View File

@@ -7,29 +7,29 @@ import { ContractArtifact } from 'ethereum-types';
import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json';
import * as FullMigration from '../generated-artifacts/FullMigration.json';
import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json';
import * as IERC20Transformer from '../generated-artifacts/IERC20Transformer.json';
import * as IFlashWallet from '../generated-artifacts/IFlashWallet.json';
import * as InitialMigration from '../generated-artifacts/InitialMigration.json';
import * as IOwnable from '../generated-artifacts/IOwnable.json';
import * as ISimpleFunctionRegistry from '../generated-artifacts/ISimpleFunctionRegistry.json';
import * as ITokenSpender from '../generated-artifacts/ITokenSpender.json';
import * as ITransformERC20 from '../generated-artifacts/ITransformERC20.json';
import * as LibERC20Transformer from '../generated-artifacts/LibERC20Transformer.json';
import * as PayTakerTransformer from '../generated-artifacts/PayTakerTransformer.json';
import * as Puppet from '../generated-artifacts/Puppet.json';
import * as WethTransformer from '../generated-artifacts/WethTransformer.json';
import * as ZeroEx from '../generated-artifacts/ZeroEx.json';
export const artifacts = {
ZeroEx: ZeroEx as ContractArtifact,
FullMigration: FullMigration as ContractArtifact,
InitialMigration: InitialMigration as ContractArtifact,
Puppet: Puppet as ContractArtifact,
IFlashWallet: IFlashWallet as ContractArtifact,
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
IERC20Transformer: IERC20Transformer as ContractArtifact,
IOwnable: IOwnable as ContractArtifact,
ISimpleFunctionRegistry: ISimpleFunctionRegistry as ContractArtifact,
ITokenSpender: ITokenSpender as ContractArtifact,
ITransformERC20: ITransformERC20 as ContractArtifact,
LibERC20Transformer: LibERC20Transformer as ContractArtifact,
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
PayTakerTransformer: PayTakerTransformer as ContractArtifact,
WethTransformer: WethTransformer as ContractArtifact,
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
};

View File

@@ -19,7 +19,7 @@ export function rlpEncodeNonce(nonce: number): string {
} else if (nonce <= 0x7f) {
return ethjs.bufferToHex(ethjs.toBuffer(nonce));
} else {
const rlpNonce = ethjs.bufferToHex(ethjs.toBuffer(nonce));
return hexUtils.concat(rlpNonce.length + 0x80, rlpNonce);
const rlpNonce = ethjs.toBuffer(nonce);
return hexUtils.concat(rlpNonce.length + 0x80, ethjs.bufferToHex(rlpNonce));
}
}

View File

@@ -5,14 +5,14 @@
*/
export * from '../generated-wrappers/fill_quote_transformer';
export * from '../generated-wrappers/full_migration';
export * from '../generated-wrappers/i_allowance_target';
export * from '../generated-wrappers/i_erc20_transformer';
export * from '../generated-wrappers/i_flash_wallet';
export * from '../generated-wrappers/i_ownable';
export * from '../generated-wrappers/i_simple_function_registry';
export * from '../generated-wrappers/i_token_spender';
export * from '../generated-wrappers/i_transform_erc20';
export * from '../generated-wrappers/initial_migration';
export * from '../generated-wrappers/lib_erc20_transformer';
export * from '../generated-wrappers/pay_taker_transformer';
export * from '../generated-wrappers/puppet';
export * from '../generated-wrappers/weth_transformer';
export * from '../generated-wrappers/zero_ex';

View File

@@ -9,15 +9,16 @@ import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.js
import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json';
import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json';
import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json';
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json';
import * as IBootstrap from '../test/generated-artifacts/IBootstrap.json';
import * as IERC20Transformer from '../test/generated-artifacts/IERC20Transformer.json';
import * as IExchange from '../test/generated-artifacts/IExchange.json';
import * as IFeature from '../test/generated-artifacts/IFeature.json';
import * as IFlashWallet from '../test/generated-artifacts/IFlashWallet.json';
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
import * as IOwnable from '../test/generated-artifacts/IOwnable.json';
import * as IPuppet from '../test/generated-artifacts/IPuppet.json';
import * as ISimpleFunctionRegistry from '../test/generated-artifacts/ISimpleFunctionRegistry.json';
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
import * as ITokenSpender from '../test/generated-artifacts/ITokenSpender.json';
@@ -30,7 +31,6 @@ import * as LibOwnableRichErrors from '../test/generated-artifacts/LibOwnableRic
import * as LibOwnableStorage from '../test/generated-artifacts/LibOwnableStorage.json';
import * as LibProxyRichErrors from '../test/generated-artifacts/LibProxyRichErrors.json';
import * as LibProxyStorage from '../test/generated-artifacts/LibProxyStorage.json';
import * as LibPuppetRichErrors from '../test/generated-artifacts/LibPuppetRichErrors.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';
@@ -38,10 +38,11 @@ import * as LibStorage from '../test/generated-artifacts/LibStorage.json';
import * as LibTokenSpenderStorage from '../test/generated-artifacts/LibTokenSpenderStorage.json';
import * as LibTransformERC20RichErrors from '../test/generated-artifacts/LibTransformERC20RichErrors.json';
import * as LibTransformERC20Storage from '../test/generated-artifacts/LibTransformERC20Storage.json';
import * as LibWalletRichErrors from '../test/generated-artifacts/LibWalletRichErrors.json';
import * as Ownable from '../test/generated-artifacts/Ownable.json';
import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json';
import * as Puppet from '../test/generated-artifacts/Puppet.json';
import * as SimpleFunctionRegistry from '../test/generated-artifacts/SimpleFunctionRegistry.json';
import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json';
import * as TestFillQuoteTransformerExchange from '../test/generated-artifacts/TestFillQuoteTransformerExchange.json';
import * as TestFillQuoteTransformerHost from '../test/generated-artifacts/TestFillQuoteTransformerHost.json';
import * as TestFullMigration from '../test/generated-artifacts/TestFullMigration.json';
@@ -49,7 +50,6 @@ import * as TestInitialMigration from '../test/generated-artifacts/TestInitialMi
import * as TestMigrator from '../test/generated-artifacts/TestMigrator.json';
import * as TestMintableERC20Token from '../test/generated-artifacts/TestMintableERC20Token.json';
import * as TestMintTokenERC20Transformer from '../test/generated-artifacts/TestMintTokenERC20Transformer.json';
import * as TestPuppetTarget from '../test/generated-artifacts/TestPuppetTarget.json';
import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json';
import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json';
import * as TestTokenSpender from '../test/generated-artifacts/TestTokenSpender.json';
@@ -68,14 +68,14 @@ export const artifacts = {
LibCommonRichErrors: LibCommonRichErrors as ContractArtifact,
LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
LibProxyRichErrors: LibProxyRichErrors as ContractArtifact,
LibPuppetRichErrors: LibPuppetRichErrors as ContractArtifact,
LibSimpleFunctionRegistryRichErrors: LibSimpleFunctionRegistryRichErrors as ContractArtifact,
LibSpenderRichErrors: LibSpenderRichErrors as ContractArtifact,
LibTransformERC20RichErrors: LibTransformERC20RichErrors as ContractArtifact,
LibWalletRichErrors: LibWalletRichErrors as ContractArtifact,
AllowanceTarget: AllowanceTarget as ContractArtifact,
FlashWallet: FlashWallet as ContractArtifact,
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
IPuppet: IPuppet as ContractArtifact,
Puppet: Puppet as ContractArtifact,
IFlashWallet: IFlashWallet as ContractArtifact,
Bootstrap: Bootstrap as ContractArtifact,
IBootstrap: IBootstrap as ContractArtifact,
IFeature: IFeature as ContractArtifact,
@@ -105,6 +105,7 @@ export const artifacts = {
WethTransformer: WethTransformer as ContractArtifact,
IExchange: IExchange as ContractArtifact,
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
TestCallTarget: TestCallTarget as ContractArtifact,
TestFillQuoteTransformerExchange: TestFillQuoteTransformerExchange as ContractArtifact,
TestFillQuoteTransformerHost: TestFillQuoteTransformerHost as ContractArtifact,
TestFullMigration: TestFullMigration as ContractArtifact,
@@ -112,7 +113,6 @@ export const artifacts = {
TestMigrator: TestMigrator as ContractArtifact,
TestMintTokenERC20Transformer: TestMintTokenERC20Transformer as ContractArtifact,
TestMintableERC20Token: TestMintableERC20Token as ContractArtifact,
TestPuppetTarget: TestPuppetTarget as ContractArtifact,
TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact,
TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact,
TestTokenSpender: TestTokenSpender as ContractArtifact,

View File

@@ -12,6 +12,7 @@ import { Order } from '@0x/types';
import { BigNumber, hexUtils, ZeroExRevertErrors } from '@0x/utils';
import * as _ from 'lodash';
import { rlpEncodeNonce } from '../../src/nonce_utils';
import { encodeFillQuoteTransformerData, FillQuoteTransformerData } from '../../src/transformer_data_encoders';
import { artifacts } from '../artifacts';
import {
@@ -24,6 +25,7 @@ import {
const { NULL_ADDRESS, NULL_BYTES, MAX_UINT256, ZERO_AMOUNT } = constants;
blockchainTests.resets('FillQuoteTransformer', env => {
const deploymentNonce = _.random(0, 0xffffffff);
let maker: string;
let feeRecipient: string;
let exchange: TestFillQuoteTransformerExchangeContract;
@@ -50,6 +52,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
env.txDefaults,
artifacts,
exchange.address,
new BigNumber(deploymentNonce),
);
host = await TestFillQuoteTransformerHostContract.deployFrom0xArtifactAsync(
artifacts.TestFillQuoteTransformerHost,
@@ -578,6 +581,24 @@ blockchainTests.resets('FillQuoteTransformer', env => {
makerAssetBalance: qfr.makerAssetBought,
});
});
it('returns the RLP-encoded nonce', async () => {
const orders = _.times(1, () => createOrder());
const signatures = orders.map(() => encodeExchangeBehavior());
const qfr = getExpectedSellQuoteFillResults(orders);
const r = await host
.executeTransform(
transformer.address,
takerToken.address,
qfr.takerAssetSpent,
encodeTransformData({
orders,
signatures,
}),
)
.callAsync({ value: qfr.protocolFeePaid });
expect(r).to.eq(rlpEncodeNonce(deploymentNonce));
});
});
describe('buy quotes', () => {
@@ -782,7 +803,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
const BAD_ASSET_DATA = hexUtils.random(36);
const orders = _.times(1, () => createOrder({ takerFeeAssetData: BAD_ASSET_DATA }));
const signatures = orders.map(() => encodeExchangeBehavior());
const qfr = getExpectedSellQuoteFillResults(orders);
const qfr = getExpectedBuyQuoteFillResults(orders);
const tx = host
.executeTransform(
transformer.address,
@@ -805,7 +826,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
const BAD_ASSET_DATA = hexUtils.concat(ERC20_ASSET_PROXY_ID, hexUtils.leftPad(badToken));
const orders = _.times(1, () => createOrder({ takerFeeAssetData: BAD_ASSET_DATA }));
const signatures = orders.map(() => encodeExchangeBehavior());
const qfr = getExpectedSellQuoteFillResults(orders);
const qfr = getExpectedBuyQuoteFillResults(orders);
const tx = host
.executeTransform(
transformer.address,
@@ -824,7 +845,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
it('respects `maxOrderFillAmounts`', async () => {
const orders = _.times(2, () => createOrder());
const signatures = orders.map(() => encodeExchangeBehavior());
const qfr = getExpectedSellQuoteFillResults(orders.slice(1));
const qfr = getExpectedBuyQuoteFillResults(orders.slice(1));
const protocolFee = singleProtocolFee.times(2);
await host
.executeTransform(
@@ -845,5 +866,23 @@ blockchainTests.resets('FillQuoteTransformer', env => {
makerAssetBalance: qfr.makerAssetBought,
});
});
it('returns the RLP-encoded nonce', async () => {
const orders = _.times(1, () => createOrder());
const signatures = orders.map(() => encodeExchangeBehavior());
const qfr = getExpectedBuyQuoteFillResults(orders);
const r = await host
.executeTransform(
transformer.address,
takerToken.address,
qfr.takerAssetSpent,
encodeTransformData({
orders,
signatures,
}),
)
.callAsync({ value: qfr.protocolFeePaid });
expect(r).to.eq(rlpEncodeNonce(deploymentNonce));
});
});
});

View File

@@ -3,6 +3,7 @@ import { BigNumber, hexUtils } from '@0x/utils';
import * as _ from 'lodash';
import { ETH_TOKEN_ADDRESS } from '../../src/constants';
import { rlpEncodeNonce } from '../../src/nonce_utils';
import { encodePayTakerTransformerData } from '../../src/transformer_data_encoders';
import { artifacts } from '../artifacts';
import { PayTakerTransformerContract, TestMintableERC20TokenContract, TestTransformerHostContract } from '../wrappers';
@@ -10,8 +11,9 @@ import { PayTakerTransformerContract, TestMintableERC20TokenContract, TestTransf
const { MAX_UINT256, ZERO_AMOUNT } = constants;
blockchainTests.resets('PayTakerTransformer', env => {
let caller: string;
const taker = randomAddress();
const deploymentNonce = _.random(0, 0xffffffff);
let caller: string;
let token: TestMintableERC20TokenContract;
let transformer: PayTakerTransformerContract;
let host: TestTransformerHostContract;
@@ -29,6 +31,7 @@ blockchainTests.resets('PayTakerTransformer', env => {
env.provider,
env.txDefaults,
artifacts,
new BigNumber(deploymentNonce),
);
host = await TestTransformerHostContract.deployFrom0xArtifactAsync(
artifacts.TestTransformerHost,
@@ -144,4 +147,16 @@ blockchainTests.resets('PayTakerTransformer', env => {
ethBalance: amounts[1].dividedToIntegerBy(2),
});
});
it('returns the RLP-encoded nonce', async () => {
const amounts = _.times(2, () => getRandomInteger(1, '1e18'));
const data = encodePayTakerTransformerData({
amounts,
tokens: [token.address, ETH_TOKEN_ADDRESS],
});
await mintHostTokensAsync(amounts[0]);
await sendEtherAsync(host.address, amounts[1]);
const r = await host.rawExecuteTransform(transformer.address, hexUtils.random(), taker, data).callAsync();
expect(r).to.eq(rlpEncodeNonce(deploymentNonce));
});
});

View File

@@ -3,6 +3,7 @@ import { BigNumber, ZeroExRevertErrors } from '@0x/utils';
import * as _ from 'lodash';
import { ETH_TOKEN_ADDRESS } from '../../src/constants';
import { rlpEncodeNonce } from '../../src/nonce_utils';
import { encodeWethTransformerData } from '../../src/transformer_data_encoders';
import { artifacts } from '../artifacts';
import { TestWethContract, TestWethTransformerHostContract, WethTransformerContract } from '../wrappers';
@@ -10,6 +11,7 @@ import { TestWethContract, TestWethTransformerHostContract, WethTransformerContr
const { MAX_UINT256, ZERO_AMOUNT } = constants;
blockchainTests.resets('WethTransformer', env => {
const deploymentNonce = _.random(0, 0xffffffff);
let weth: TestWethContract;
let transformer: WethTransformerContract;
let host: TestWethTransformerHostContract;
@@ -27,6 +29,7 @@ blockchainTests.resets('WethTransformer', env => {
env.txDefaults,
artifacts,
weth.address,
new BigNumber(deploymentNonce),
);
host = await TestWethTransformerHostContract.deployFrom0xArtifactAsync(
artifacts.TestWethTransformerHost,
@@ -144,4 +147,14 @@ blockchainTests.resets('WethTransformer', env => {
wethBalance: amount.dividedToIntegerBy(2),
});
});
it('returns the RLP-encoded nonce', async () => {
const amount = getRandomInteger(1, '1e18');
const data = encodeWethTransformerData({
amount,
token: weth.address,
});
const r = await host.executeTransform(amount, transformer.address, data).callAsync({ value: amount });
expect(r).to.eq(rlpEncodeNonce(deploymentNonce));
});
});

View File

@@ -39,8 +39,11 @@ export * from '../test/generated-wrappers/lib_transform_erc20_rich_errors';
export * from '../test/generated-wrappers/lib_transform_erc20_storage';
export * from '../test/generated-wrappers/lib_wallet_rich_errors';
export * from '../test/generated-wrappers/ownable';
export * from '../test/generated-wrappers/pay_taker_transformer';
export * from '../test/generated-wrappers/simple_function_registry';
export * from '../test/generated-wrappers/test_call_target';
export * from '../test/generated-wrappers/test_fill_quote_transformer_exchange';
export * from '../test/generated-wrappers/test_fill_quote_transformer_host';
export * from '../test/generated-wrappers/test_full_migration';
export * from '../test/generated-wrappers/test_initial_migration';
export * from '../test/generated-wrappers/test_migrator';

View File

@@ -13,6 +13,8 @@
"generated-artifacts/ITokenSpender.json",
"generated-artifacts/ITransformERC20.json",
"generated-artifacts/InitialMigration.json",
"generated-artifacts/PayTakerTransformer.json",
"generated-artifacts/WethTransformer.json",
"generated-artifacts/ZeroEx.json",
"test/generated-artifacts/AllowanceTarget.json",
"test/generated-artifacts/Bootstrap.json",
@@ -50,8 +52,11 @@
"test/generated-artifacts/LibTransformERC20Storage.json",
"test/generated-artifacts/LibWalletRichErrors.json",
"test/generated-artifacts/Ownable.json",
"test/generated-artifacts/PayTakerTransformer.json",
"test/generated-artifacts/SimpleFunctionRegistry.json",
"test/generated-artifacts/TestCallTarget.json",
"test/generated-artifacts/TestFillQuoteTransformerExchange.json",
"test/generated-artifacts/TestFillQuoteTransformerHost.json",
"test/generated-artifacts/TestFullMigration.json",
"test/generated-artifacts/TestInitialMigration.json",
"test/generated-artifacts/TestMigrator.json",