@0x/contracts-exchange: Add MultiAssetProxy, ERC1155Fungible, and ERC1155NonFungible combinatorial tests.
This commit is contained in:
committed by
Amir Bandeali
parent
741fdfa52e
commit
85ea291745
@@ -9,7 +9,6 @@ import {
|
||||
ExpirationTimeSecondsScenario,
|
||||
FeeAssetDataScenario,
|
||||
FeeRecipientAddressScenario,
|
||||
FillScenario,
|
||||
OrderAssetAmountScenario,
|
||||
TakerAssetFillAmountScenario,
|
||||
TakerScenario,
|
||||
@@ -52,7 +51,7 @@ const defaultFillScenario = {
|
||||
},
|
||||
};
|
||||
|
||||
describe('FillOrder Tests', () => {
|
||||
describe.only('FillOrder Tests', () => {
|
||||
let fillOrderCombinatorialUtils: FillOrderCombinatorialUtils;
|
||||
|
||||
before(async () => {
|
||||
@@ -68,26 +67,7 @@ describe('FillOrder Tests', () => {
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('fillOrder', () => {
|
||||
const test = (fillScenarios: FillScenario[]) => {
|
||||
_.forEach(fillScenarios, fillScenario => {
|
||||
const description = `Combinatorial OrderFill: ${JSON.stringify(fillScenario)}`;
|
||||
it(description, async () => {
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(fillScenario);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const allFillScenarios = FillOrderCombinatorialUtils.generateFillOrderCombinations();
|
||||
describe('Combinatorially generated fills orders', () => test(allFillScenarios));
|
||||
|
||||
it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
describe('Fill tests', () => {
|
||||
it('should transfer the correct amounts when makerAssetAmount > takerAssetAmount', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
@@ -141,38 +121,6 @@ describe('FillOrder Tests', () => {
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay maker fee with taker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with maker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should throw when taker is specified and order is claimed by other', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
@@ -226,8 +174,92 @@ describe('FillOrder Tests', () => {
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw if maker erc20Balances are too low to fill order', async () => {
|
||||
describe('ERC20', () => {
|
||||
it('should be able to pay maker fee with taker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with maker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should not be able to pay maker fee with maker asset if none is left over (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
traderAssetBalance: BalanceAmountScenario.Exact,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should not be able to pay taker fee with taker asset if none is left over (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
traderAssetBalance: BalanceAmountScenario.Exact,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with maker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should throw if maker balance is too low to fill order', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
makerStateScenario: {
|
||||
@@ -238,7 +270,7 @@ describe('FillOrder Tests', () => {
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should throw if taker erc20Balances are too low to fill order', async () => {
|
||||
it('should throw if taker balance is too low to fill order', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
takerStateScenario: {
|
||||
@@ -271,7 +303,7 @@ describe('FillOrder Tests', () => {
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should throw if maker fee erc20Balances are too low to fill order', async () => {
|
||||
it('should throw if maker fee balance is too low to fill order', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
makerStateScenario: {
|
||||
@@ -282,7 +314,7 @@ describe('FillOrder Tests', () => {
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should throw if taker fee erc20Balances are too low to fill order', async () => {
|
||||
it('should throw if taker fee balance is too low to fill order', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
takerStateScenario: {
|
||||
@@ -316,85 +348,8 @@ describe('FillOrder Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing exchange of ERC721 Tokens', () => {
|
||||
it('should successfully exchange a single token between the maker and taker (via fillOrder)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
takerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should successfully fill order when makerAsset is ERC721 and takerAsset is ERC20', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
takerAssetDataScenario: AssetDataScenario.ERC20EighteenDecimals,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should successfully fill order when makerAsset is ERC20 and takerAsset is ERC721', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC20EighteenDecimals,
|
||||
takerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should successfully fill order when makerAsset is ERC721 and approveAll is set for it', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
takerAssetDataScenario: AssetDataScenario.ERC20EighteenDecimals,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
traderAssetAllowance: AllowanceAmountScenario.Unlimited,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should successfully fill order when makerAsset and takerAsset are ERC721 and approveAll is set for them', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
takerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
traderAssetAllowance: AllowanceAmountScenario.Unlimited,
|
||||
},
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
traderAssetAllowance: AllowanceAmountScenario.Unlimited,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay maker fee with taker asset', async () => {
|
||||
describe('ERC721', () => {
|
||||
it('should be able to pay maker fee with taker ERC721', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
@@ -406,13 +361,12 @@ describe('FillOrder Tests', () => {
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
feeAllowance: AllowanceAmountScenario.Unlimited,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with maker asset', async () => {
|
||||
it('should be able to pay taker fee with maker ERC721', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
@@ -424,10 +378,259 @@ describe('FillOrder Tests', () => {
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
feeAllowance: AllowanceAmountScenario.Unlimited,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should not be able to pay maker fee with maker ERC721 (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with taker ERC721 (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerAssetDataScenario: AssetDataScenario.ERC721,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ERC1155', () => {
|
||||
const assetTypes = [AssetDataScenario.ERC1155Fungible, AssetDataScenario.ERC1155NonFungible];
|
||||
for (const assetType of assetTypes) {
|
||||
describe(_.startCase(_.toLower((/ERC1155(.+)/.exec(assetType) as string[])[1])), () => {
|
||||
it('should be able to pay maker fee with taker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerAssetDataScenario: assetType,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with maker asset', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: assetType,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should not be able to pay maker fee with maker asset if not enough left (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: assetType,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
traderAssetBalance: BalanceAmountScenario.Exact,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with taker asset if not enough left (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerAssetDataScenario: assetType,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
traderAssetBalance: BalanceAmountScenario.Exact,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('MultiAssetProxy', () => {
|
||||
it('should be able to pay maker fee with taker MAP', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerAssetDataScenario: AssetDataScenario.MultiAssetERC20,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with maker MAP', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.MultiAssetERC20,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should not be able to pay maker fee with maker MAP (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: AssetDataScenario.MultiAssetERC20,
|
||||
makerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
makerStateScenario: {
|
||||
...defaultFillScenario.makerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
|
||||
it('should be able to pay taker fee with taker MAP (double-spend)', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
takerAssetDataScenario: AssetDataScenario.MultiAssetERC20,
|
||||
takerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
takerStateScenario: {
|
||||
...defaultFillScenario.takerStateScenario,
|
||||
feeBalance: BalanceAmountScenario.Zero,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Maker/taker asset combinations', () => {
|
||||
const assetDataScenarios = [
|
||||
AssetDataScenario.ERC20EighteenDecimals,
|
||||
AssetDataScenario.ERC721,
|
||||
AssetDataScenario.ERC1155Fungible,
|
||||
AssetDataScenario.ERC1155NonFungible,
|
||||
AssetDataScenario.MultiAssetERC20,
|
||||
];
|
||||
for (const [makerAssetData, takerAssetData] of getAllPossiblePairs(assetDataScenarios)) {
|
||||
it(`should successfully exchange ${makerAssetData} for ${takerAssetData}`, async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetDataScenario: makerAssetData,
|
||||
takerAssetDataScenario: takerAssetData,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Maker/taker fee asset combinations', () => {
|
||||
const feeAssetDataScenarios = [
|
||||
FeeAssetDataScenario.ERC20EighteenDecimals,
|
||||
FeeAssetDataScenario.ERC721,
|
||||
FeeAssetDataScenario.ERC1155Fungible,
|
||||
FeeAssetDataScenario.ERC1155NonFungible,
|
||||
FeeAssetDataScenario.MultiAssetERC20,
|
||||
];
|
||||
for (const [makerFeeAssetData, takerFeeAssetData] of getAllPossiblePairs(feeAssetDataScenarios)) {
|
||||
it(`should successfully pay maker fee ${makerFeeAssetData} and taker fee ${takerFeeAssetData}`, async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerFeeAssetDataScenario: makerFeeAssetData,
|
||||
takerFeeAssetDataScenario: takerFeeAssetData,
|
||||
},
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Combinatorially generated fills orders', () => {
|
||||
const allFillScenarios = FillOrderCombinatorialUtils.generateFillOrderCombinations();
|
||||
for (const fillScenario of allFillScenarios) {
|
||||
const description = `Combinatorial OrderFill: ${JSON.stringify(fillScenario)}`;
|
||||
it(description, async () => {
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(fillScenario);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getAllPossiblePairs<T>(choices: T[]): Array<[T, T]> {
|
||||
const pairs: Array<[T, T]> = [];
|
||||
for (const i of _.times(choices.length)) {
|
||||
for (const j of _.times(choices.length)) {
|
||||
pairs.push([choices[i], choices[j]]);
|
||||
}
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
// tslint:disable: max-file-line-count
|
||||
|
||||
@@ -4,20 +4,25 @@ import { AssetProxyId } from '@0x/types';
|
||||
import { BigNumber, errorUtils } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
|
||||
import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
|
||||
|
||||
interface ProxyIdToAssetWrappers {
|
||||
[proxyId: string]: AbstractAssetWrapper;
|
||||
}
|
||||
|
||||
const ONE_NFT_UNIT = new BigNumber(1);
|
||||
const ZERO_NFT_UNIT = new BigNumber(0);
|
||||
|
||||
/**
|
||||
* This class abstracts away the differences between ERC20 and ERC721 tokens so that
|
||||
* the logic that uses it does not need to care what standard a token belongs to.
|
||||
*/
|
||||
export class AssetWrapper {
|
||||
private readonly _proxyIdToAssetWrappers: ProxyIdToAssetWrappers;
|
||||
constructor(assetWrappers: AbstractAssetWrapper[]) {
|
||||
private readonly _burnerAddress: string;
|
||||
constructor(assetWrappers: AbstractAssetWrapper[], burnerAddress: string) {
|
||||
this._proxyIdToAssetWrappers = {};
|
||||
this._burnerAddress = burnerAddress;
|
||||
_.each(assetWrappers, assetWrapper => {
|
||||
const proxyId = assetWrapper.getProxyId();
|
||||
this._proxyIdToAssetWrappers[proxyId] = assetWrapper;
|
||||
@@ -41,9 +46,31 @@ export class AssetWrapper {
|
||||
assetProxyData.tokenAddress,
|
||||
assetProxyData.tokenId,
|
||||
);
|
||||
const balance = isOwner ? new BigNumber(1) : new BigNumber(0);
|
||||
const balance = isOwner ? ONE_NFT_UNIT : ZERO_NFT_UNIT;
|
||||
return balance;
|
||||
}
|
||||
case AssetProxyId.ERC1155: {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
|
||||
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData);
|
||||
const assetWrapper = assetProxyWrapper.getContractWrapper(assetProxyData.tokenAddress);
|
||||
const balances = await Promise.all(
|
||||
_.map(assetProxyData.tokenIds).map(tokenId => assetWrapper.getBalanceAsync(userAddress, tokenId)),
|
||||
);
|
||||
return BigNumber.min(...balances);
|
||||
}
|
||||
case AssetProxyId.MultiAsset: {
|
||||
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData);
|
||||
const nestedBalances = await Promise.all(
|
||||
assetProxyData.nestedAssetData.map(async nestedAssetData =>
|
||||
this.getBalanceAsync(userAddress, nestedAssetData),
|
||||
),
|
||||
);
|
||||
const scaledBalances = _.zip(assetProxyData.amounts, nestedBalances).map(([amount, balance]) =>
|
||||
(balance as BigNumber).div(amount as BigNumber).integerValue(BigNumber.ROUND_HALF_UP),
|
||||
);
|
||||
return BigNumber.min(...scaledBalances);
|
||||
}
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('proxyId', proxyId);
|
||||
}
|
||||
@@ -54,13 +81,14 @@ export class AssetWrapper {
|
||||
case AssetProxyId.ERC20: {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const erc20Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC20Wrapper;
|
||||
await erc20Wrapper.setBalanceAsync(userAddress, assetData, desiredBalance);
|
||||
await erc20Wrapper.setBalanceAsync(
|
||||
userAddress,
|
||||
assetData,
|
||||
desiredBalance.integerValue(BigNumber.ROUND_DOWN),
|
||||
);
|
||||
return;
|
||||
}
|
||||
case AssetProxyId.ERC721: {
|
||||
if (!desiredBalance.eq(0) && !desiredBalance.eq(1)) {
|
||||
throw new Error(`Balance for ERC721 token can only be set to 0 or 1. Got: ${desiredBalance}`);
|
||||
}
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
|
||||
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData);
|
||||
@@ -68,42 +96,137 @@ export class AssetWrapper {
|
||||
assetProxyData.tokenAddress,
|
||||
assetProxyData.tokenId,
|
||||
);
|
||||
if (!doesTokenExist && desiredBalance.eq(1)) {
|
||||
if (!doesTokenExist && desiredBalance.gt(0)) {
|
||||
await erc721Wrapper.mintAsync(assetProxyData.tokenAddress, assetProxyData.tokenId, userAddress);
|
||||
return;
|
||||
} else if (!doesTokenExist && desiredBalance.eq(0)) {
|
||||
} else if (!doesTokenExist && desiredBalance.lte(0)) {
|
||||
return; // noop
|
||||
}
|
||||
const tokenOwner = await erc721Wrapper.ownerOfAsync(
|
||||
assetProxyData.tokenAddress,
|
||||
assetProxyData.tokenId,
|
||||
);
|
||||
if (userAddress !== tokenOwner && desiredBalance.eq(1)) {
|
||||
if (userAddress !== tokenOwner && desiredBalance.gt(0)) {
|
||||
await erc721Wrapper.transferFromAsync(
|
||||
assetProxyData.tokenAddress,
|
||||
assetProxyData.tokenId,
|
||||
tokenOwner,
|
||||
userAddress,
|
||||
);
|
||||
} else if (tokenOwner === userAddress && desiredBalance.eq(0)) {
|
||||
// Transfer token to someone else
|
||||
const userAddresses = await (erc721Wrapper as any)._web3Wrapper.getAvailableAddressesAsync();
|
||||
const nonOwner = _.find(userAddresses, a => a !== userAddress);
|
||||
} else if (tokenOwner === userAddress && desiredBalance.lte(0)) {
|
||||
// Burn token
|
||||
await erc721Wrapper.transferFromAsync(
|
||||
assetProxyData.tokenAddress,
|
||||
assetProxyData.tokenId,
|
||||
tokenOwner,
|
||||
nonOwner,
|
||||
this._burnerAddress,
|
||||
);
|
||||
return;
|
||||
} else if (
|
||||
(userAddress !== tokenOwner && desiredBalance.eq(0)) ||
|
||||
(tokenOwner === userAddress && desiredBalance.eq(1))
|
||||
(userAddress !== tokenOwner && desiredBalance.lte(0)) ||
|
||||
(tokenOwner === userAddress && desiredBalance.gt(0))
|
||||
) {
|
||||
return; // noop
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AssetProxyId.ERC1155: {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
|
||||
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData);
|
||||
const assetWrapper = assetProxyWrapper.getContractWrapper(assetProxyData.tokenAddress);
|
||||
const tokenValuesSum = BigNumber.sum(...assetProxyData.tokenValues);
|
||||
let tokenValueRatios = assetProxyData.tokenValues;
|
||||
if (!tokenValuesSum.eq(0)) {
|
||||
tokenValueRatios = assetProxyData.tokenValues.map(v => v.div(tokenValuesSum));
|
||||
}
|
||||
for (const i of _.times(assetProxyData.tokenIds.length)) {
|
||||
const tokenId = assetProxyData.tokenIds[i];
|
||||
const tokenValueRatio = tokenValueRatios[i];
|
||||
const scaledDesiredBalance = desiredBalance.times(tokenValueRatio);
|
||||
const isFungible = await assetWrapper.isFungibleItemAsync(tokenId);
|
||||
if (isFungible) {
|
||||
// Token is fungible.
|
||||
const currentBalance = await assetWrapper.getBalanceAsync(userAddress, tokenId);
|
||||
const difference = scaledDesiredBalance
|
||||
.minus(currentBalance)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
if (difference.eq(0)) {
|
||||
// Just right. Nothing to do.
|
||||
} else if (difference.lt(0)) {
|
||||
// Too much. Burn some tokens.
|
||||
await assetWrapper.safeTransferFromAsync(
|
||||
userAddress,
|
||||
this._burnerAddress,
|
||||
tokenId,
|
||||
difference.abs(),
|
||||
);
|
||||
} else {
|
||||
// difference.gt(0)
|
||||
// Too little. Mint some tokens.
|
||||
await assetWrapper.mintKnownFungibleTokensAsync(tokenId, [userAddress], [difference]);
|
||||
}
|
||||
} else {
|
||||
const nftOwner = await assetWrapper.getOwnerOfAsync(tokenId);
|
||||
if (scaledDesiredBalance.gt(0)) {
|
||||
if (nftOwner === userAddress) {
|
||||
// Nothing to do.
|
||||
} else if (nftOwner !== constants.NULL_ADDRESS) {
|
||||
// Transfer from current owner.
|
||||
await assetWrapper.safeTransferFromAsync(nftOwner, userAddress, tokenId, ONE_NFT_UNIT);
|
||||
} else {
|
||||
throw new Error(`Cannot mint new ERC1155 tokens with a specific token ID.`);
|
||||
}
|
||||
} else {
|
||||
if (nftOwner === userAddress) {
|
||||
// Burn the token.
|
||||
await assetWrapper.safeTransferFromAsync(
|
||||
userAddress,
|
||||
this._burnerAddress,
|
||||
tokenId,
|
||||
ONE_NFT_UNIT,
|
||||
);
|
||||
} else {
|
||||
// Nothing to do.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AssetProxyId.MultiAsset: {
|
||||
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData);
|
||||
const amountsSum = BigNumber.sum(...assetProxyData.amounts);
|
||||
let assetAmountRatios = assetProxyData.amounts;
|
||||
if (!amountsSum.eq(0)) {
|
||||
assetAmountRatios = assetProxyData.amounts.map(amt => amt.div(amountsSum));
|
||||
}
|
||||
for (const i of _.times(assetProxyData.amounts.length)) {
|
||||
const nestedAssetData = assetProxyData.nestedAssetData[i];
|
||||
const assetAmountRatio = assetAmountRatios[i];
|
||||
await this.setBalanceAsync(userAddress, nestedAssetData, desiredBalance.times(assetAmountRatio));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('proxyId', proxyId);
|
||||
}
|
||||
}
|
||||
public async setUnscaledBalanceAsync(
|
||||
userAddress: string,
|
||||
assetData: string,
|
||||
desiredBalance: BigNumber,
|
||||
): Promise<void> {
|
||||
const proxyId = assetDataUtils.decodeAssetProxyId(assetData);
|
||||
switch (proxyId) {
|
||||
case AssetProxyId.ERC20:
|
||||
case AssetProxyId.ERC721:
|
||||
return this.setBalanceAsync(userAddress, assetData, desiredBalance);
|
||||
case AssetProxyId.ERC1155:
|
||||
case AssetProxyId.MultiAsset: {
|
||||
const currentBalance = await this.getBalanceAsync(userAddress, assetData);
|
||||
return this.setBalanceAsync(userAddress, assetData, desiredBalance.times(currentBalance));
|
||||
}
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('proxyId', proxyId);
|
||||
}
|
||||
@@ -133,9 +256,32 @@ export class AssetWrapper {
|
||||
erc721ProxyData.tokenAddress,
|
||||
erc721ProxyData.tokenId,
|
||||
);
|
||||
const allowance = isProxyApproved ? new BigNumber(1) : new BigNumber(0);
|
||||
const allowance = isProxyApproved ? ONE_NFT_UNIT : ZERO_NFT_UNIT;
|
||||
return allowance;
|
||||
}
|
||||
case AssetProxyId.ERC1155: {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
|
||||
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData);
|
||||
const isApprovedForAll = await assetProxyWrapper.isProxyApprovedForAllAsync(
|
||||
userAddress,
|
||||
assetProxyData.tokenAddress,
|
||||
);
|
||||
if (!isApprovedForAll) {
|
||||
// ERC1155 is all or nothing.
|
||||
return constants.ZERO_AMOUNT;
|
||||
}
|
||||
return constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||
}
|
||||
case AssetProxyId.MultiAsset: {
|
||||
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData);
|
||||
const allowances = await Promise.all(
|
||||
assetProxyData.nestedAssetData.map(async nestedAssetData =>
|
||||
this.getProxyAllowanceAsync(userAddress, nestedAssetData),
|
||||
),
|
||||
);
|
||||
return BigNumber.min(...allowances);
|
||||
}
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('proxyId', proxyId);
|
||||
}
|
||||
@@ -209,9 +355,37 @@ export class AssetWrapper {
|
||||
(!isProxyApproved && desiredAllowance.eq(0)) ||
|
||||
(isProxyApproved && desiredAllowance.eq(1))
|
||||
) {
|
||||
return; // noop
|
||||
// noop
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case AssetProxyId.ERC1155: {
|
||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
|
||||
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData);
|
||||
// ERC1155 allowances are all or nothing.
|
||||
const shouldApprovedForAll = desiredAllowance.gt(0);
|
||||
const currentAllowance = await this.getProxyAllowanceAsync(userAddress, assetData);
|
||||
if (shouldApprovedForAll && currentAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
|
||||
// Nothing to do.
|
||||
} else if (!shouldApprovedForAll && currentAllowance.eq(constants.ZERO_AMOUNT)) {
|
||||
// Nothing to do.
|
||||
} else {
|
||||
assetProxyWrapper.setProxyAllowanceForAllAsync(
|
||||
userAddress,
|
||||
assetProxyData.tokenAddress,
|
||||
shouldApprovedForAll,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AssetProxyId.MultiAsset: {
|
||||
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData);
|
||||
await Promise.all(
|
||||
assetProxyData.nestedAssetData.map(async nestedAssetData =>
|
||||
this.setProxyAllowanceAsync(userAddress, nestedAssetData, desiredAllowance),
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
|
||||
import { chaiSetup, constants, FillResults, orderUtils, signingUtils } from '@0x/contracts-test-utils';
|
||||
import {
|
||||
assetDataUtils,
|
||||
BalanceAndProxyAllowanceLazyStore,
|
||||
ExchangeRevertErrors,
|
||||
orderHashUtils,
|
||||
} from '@0x/order-utils';
|
||||
import { AssetProxyId, Order, SignatureType, SignedOrder } from '@0x/types';
|
||||
artifacts as assetProxyArtifacts,
|
||||
ERC1155ProxyWrapper,
|
||||
ERC20Wrapper,
|
||||
ERC721Wrapper,
|
||||
MultiAssetProxyContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import { chaiSetup, constants, FillResults, orderUtils, signingUtils } from '@0x/contracts-test-utils';
|
||||
import { BalanceAndProxyAllowanceLazyStore, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
|
||||
import { Order, SignatureType, SignedOrder } from '@0x/types';
|
||||
import { BigNumber, errorUtils, providerUtils, RevertError, StringRevertError } from '@0x/utils';
|
||||
import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
@@ -30,12 +31,10 @@ import {
|
||||
OrderScenario,
|
||||
TakerAssetFillAmountScenario,
|
||||
TakerScenario,
|
||||
TraderStateScenario,
|
||||
} from './fill_order_scenarios';
|
||||
import { FillOrderError, FillOrderSimulator } from './fill_order_simulator';
|
||||
import { OrderFactoryFromScenario } from './order_factory_from_scenario';
|
||||
import { SimpleAssetBalanceAndProxyAllowanceFetcher } from './simple_asset_balance_and_proxy_allowance_fetcher';
|
||||
import { SimpleOrderFilledCancelledFetcher } from './simple_order_filled_cancelled_fetcher';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -66,7 +65,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
): Promise<FillOrderCombinatorialUtils> {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const userAddresses = _.slice(accounts, 0, 5);
|
||||
const [ownerAddress, makerAddress, takerAddress] = userAddresses;
|
||||
const [ownerAddress, makerAddress, takerAddress, burnerAddress] = userAddresses;
|
||||
const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)];
|
||||
|
||||
const supportedProvider = web3Wrapper.getProvider();
|
||||
@@ -74,6 +73,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
const chainId = await providerUtils.getChainIdAsync(provider);
|
||||
const erc20Wrapper = new ERC20Wrapper(provider, userAddresses, ownerAddress);
|
||||
const erc721Wrapper = new ERC721Wrapper(provider, userAddresses, ownerAddress);
|
||||
const erc1155Wrapper = new ERC1155ProxyWrapper(provider, userAddresses, ownerAddress);
|
||||
|
||||
const erc20EighteenDecimalTokenCount = 4;
|
||||
const eighteenDecimals = new BigNumber(18);
|
||||
@@ -82,12 +82,12 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
eighteenDecimals,
|
||||
);
|
||||
|
||||
const erc20FiveDecimalTokenCount = 2;
|
||||
const erc20FiveDecimalTokenCount = 4;
|
||||
const fiveDecimals = new BigNumber(5);
|
||||
const erc20FiveDecimalTokens = await erc20Wrapper.deployDummyTokensAsync(erc20FiveDecimalTokenCount, fiveDecimals);
|
||||
|
||||
const erc20ZeroDecimalTokenCount = 4;
|
||||
const zeroDecimals = new BigNumber(0);
|
||||
const erc20ZeroDecimalTokenCount = 2;
|
||||
const erc20ZeroDecimalTokens = await erc20Wrapper.deployDummyTokensAsync(erc20ZeroDecimalTokenCount, zeroDecimals);
|
||||
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||
@@ -97,7 +97,18 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
||||
|
||||
const assetWrapper = new AssetWrapper([erc20Wrapper, erc721Wrapper]);
|
||||
const [erc1155Token] = (await erc1155Wrapper.deployDummyContractsAsync()).map(w => w.getContract());
|
||||
const erc1155Proxy = await erc1155Wrapper.deployProxyAsync();
|
||||
await erc1155Wrapper.setBalancesAndAllowancesAsync();
|
||||
const erc1155Holdings = await erc1155Wrapper.getBalancesAsync();
|
||||
|
||||
const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
assetProxyArtifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
|
||||
const assetWrapper = new AssetWrapper([erc20Wrapper, erc721Wrapper, erc1155Wrapper], burnerAddress);
|
||||
|
||||
const exchangeContract = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Exchange,
|
||||
@@ -108,13 +119,66 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
const exchangeWrapper = new ExchangeWrapper(exchangeContract, provider);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, ownerAddress);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, ownerAddress);
|
||||
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, ownerAddress);
|
||||
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeContract.address, { from: ownerAddress }),
|
||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchangeContract.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeContract.address, { from: ownerAddress }),
|
||||
|
||||
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchangeContract.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchangeContract.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
exchangeContract.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
multiAssetProxy.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
multiAssetProxy.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||
multiAssetProxy.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||
erc20Proxy.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||
erc721Proxy.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(
|
||||
erc1155Proxy.address,
|
||||
{ from: ownerAddress },
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
|
||||
@@ -123,8 +187,10 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
erc20EighteenDecimalTokens.map(token => token.address),
|
||||
erc20FiveDecimalTokens.map(token => token.address),
|
||||
erc20ZeroDecimalTokens.map(token => token.address),
|
||||
erc721Token,
|
||||
erc721Token.address,
|
||||
erc1155Token.address,
|
||||
erc721Balances,
|
||||
erc1155Holdings,
|
||||
exchangeContract.address,
|
||||
chainId,
|
||||
);
|
||||
@@ -152,7 +218,6 @@ export class FillOrderCombinatorialUtils {
|
||||
public exchangeWrapper: ExchangeWrapper;
|
||||
public assetWrapper: AssetWrapper;
|
||||
public balanceAndProxyAllowanceFetcher: SimpleAssetBalanceAndProxyAllowanceFetcher;
|
||||
public orderFilledCancelledFetcher: SimpleOrderFilledCancelledFetcher;
|
||||
|
||||
public static generateFillOrderCombinations(): FillScenario[] {
|
||||
const takerScenarios = [
|
||||
@@ -192,16 +257,25 @@ export class FillOrderCombinatorialUtils {
|
||||
AssetDataScenario.ERC20FiveDecimals,
|
||||
AssetDataScenario.ERC20EighteenDecimals,
|
||||
AssetDataScenario.ERC721,
|
||||
AssetDataScenario.ERC1155Fungible,
|
||||
AssetDataScenario.ERC1155NonFungible,
|
||||
AssetDataScenario.MultiAssetERC20,
|
||||
];
|
||||
const takerAssetDataScenario = [
|
||||
AssetDataScenario.ERC20FiveDecimals,
|
||||
AssetDataScenario.ERC20EighteenDecimals,
|
||||
AssetDataScenario.ERC721,
|
||||
AssetDataScenario.ERC1155Fungible,
|
||||
AssetDataScenario.ERC1155NonFungible,
|
||||
AssetDataScenario.MultiAssetERC20,
|
||||
];
|
||||
const makerFeeAssetDataScenario = [
|
||||
FeeAssetDataScenario.ERC20FiveDecimals,
|
||||
FeeAssetDataScenario.ERC20EighteenDecimals,
|
||||
FeeAssetDataScenario.ERC721,
|
||||
FeeAssetDataScenario.ERC1155Fungible,
|
||||
FeeAssetDataScenario.ERC1155NonFungible,
|
||||
FeeAssetDataScenario.MultiAssetERC20,
|
||||
FeeAssetDataScenario.MakerToken,
|
||||
FeeAssetDataScenario.TakerToken,
|
||||
];
|
||||
@@ -209,6 +283,9 @@ export class FillOrderCombinatorialUtils {
|
||||
FeeAssetDataScenario.ERC20FiveDecimals,
|
||||
FeeAssetDataScenario.ERC20EighteenDecimals,
|
||||
FeeAssetDataScenario.ERC721,
|
||||
FeeAssetDataScenario.ERC1155Fungible,
|
||||
FeeAssetDataScenario.ERC1155NonFungible,
|
||||
FeeAssetDataScenario.MultiAssetERC20,
|
||||
FeeAssetDataScenario.MakerToken,
|
||||
FeeAssetDataScenario.TakerToken,
|
||||
];
|
||||
@@ -374,7 +451,6 @@ export class FillOrderCombinatorialUtils {
|
||||
this.exchangeWrapper = exchangeWrapper;
|
||||
this.assetWrapper = assetWrapper;
|
||||
this.balanceAndProxyAllowanceFetcher = new SimpleAssetBalanceAndProxyAllowanceFetcher(assetWrapper);
|
||||
this.orderFilledCancelledFetcher = new SimpleOrderFilledCancelledFetcher(exchangeWrapper);
|
||||
}
|
||||
|
||||
public async testFillOrderScenarioAsync(fillScenario: FillScenario): Promise<void> {
|
||||
@@ -399,17 +475,9 @@ export class FillOrderCombinatorialUtils {
|
||||
): Promise<void> {
|
||||
const lazyStore = new BalanceAndProxyAllowanceLazyStore(this.balanceAndProxyAllowanceFetcher);
|
||||
const signedOrder = await this._generateSignedOrder(fillScenario.orderScenario);
|
||||
const takerAssetFillAmount = getTakerAssetFillAmountAsync(
|
||||
signedOrder,
|
||||
fillScenario.takerAssetFillAmountScenario,
|
||||
);
|
||||
const takerAssetFillAmount = getTakerAssetFillAmount(signedOrder, fillScenario);
|
||||
|
||||
await this._modifyTraderStateAsync(
|
||||
fillScenario.makerStateScenario,
|
||||
fillScenario.takerStateScenario,
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
);
|
||||
await this._modifyTraderStateAsync(fillScenario, signedOrder, takerAssetFillAmount);
|
||||
|
||||
let expectedFillResults = EMPTY_FILL_RESULTS;
|
||||
let _fillErrorIfExists = fillErrorIfExists;
|
||||
@@ -473,26 +541,38 @@ export class FillOrderCombinatorialUtils {
|
||||
const takerFeeAssetData = signedOrder.takerAssetData;
|
||||
const feeRecipient = signedOrder.feeRecipientAddress;
|
||||
|
||||
const expMakerAssetBalanceOfMaker = await lazyStore.getBalanceAsync(makerAssetData, makerAddress);
|
||||
const expMakerAssetAllowanceOfMaker = await lazyStore.getProxyAllowanceAsync(makerAssetData, makerAddress);
|
||||
const expTakerAssetBalanceOfMaker = await lazyStore.getBalanceAsync(takerAssetData, makerAddress);
|
||||
const expMakerFeeAssetBalanceOfMaker = await lazyStore.getBalanceAsync(makerFeeAssetData, makerAddress);
|
||||
const expTakerFeeAssetBalanceOfMaker = await lazyStore.getBalanceAsync(takerFeeAssetData, makerAddress);
|
||||
const expMakerFeeAssetAllowanceOfMaker = await lazyStore.getProxyAllowanceAsync(
|
||||
makerFeeAssetData,
|
||||
makerAddress,
|
||||
);
|
||||
const expTakerAssetBalanceOfTaker = await lazyStore.getBalanceAsync(takerAssetData, this.takerAddress);
|
||||
const expTakerAssetAllowanceOfTaker = await lazyStore.getProxyAllowanceAsync(takerAssetData, this.takerAddress);
|
||||
const expMakerAssetBalanceOfTaker = await lazyStore.getBalanceAsync(makerAssetData, this.takerAddress);
|
||||
const expMakerFeeAssetBalanceOfTaker = await lazyStore.getBalanceAsync(makerFeeAssetData, this.takerAddress);
|
||||
const expTakerFeeAssetBalanceOfTaker = await lazyStore.getBalanceAsync(takerFeeAssetData, this.takerAddress);
|
||||
const expTakerFeeAssetAllowanceOfTaker = await lazyStore.getProxyAllowanceAsync(
|
||||
takerFeeAssetData,
|
||||
this.takerAddress,
|
||||
);
|
||||
const expMakerFeeAssetBalanceOfFeeRecipient = await lazyStore.getBalanceAsync(makerFeeAssetData, feeRecipient);
|
||||
const expTakerFeeAssetBalanceOfFeeRecipient = await lazyStore.getBalanceAsync(takerFeeAssetData, feeRecipient);
|
||||
const [
|
||||
expMakerAssetBalanceOfMaker,
|
||||
expMakerAssetAllowanceOfMaker,
|
||||
expTakerAssetBalanceOfMaker,
|
||||
expMakerFeeAssetBalanceOfMaker,
|
||||
expTakerFeeAssetBalanceOfMaker,
|
||||
expMakerFeeAssetAllowanceOfMaker,
|
||||
expTakerAssetBalanceOfTaker,
|
||||
expTakerAssetAllowanceOfTaker,
|
||||
expMakerAssetBalanceOfTaker,
|
||||
expMakerFeeAssetBalanceOfTaker,
|
||||
expTakerFeeAssetBalanceOfTaker,
|
||||
expTakerFeeAssetAllowanceOfTaker,
|
||||
expMakerFeeAssetBalanceOfFeeRecipient,
|
||||
expTakerFeeAssetBalanceOfFeeRecipient,
|
||||
] = await Promise.all([
|
||||
lazyStore.getBalanceAsync(makerAssetData, makerAddress),
|
||||
lazyStore.getProxyAllowanceAsync(makerAssetData, makerAddress),
|
||||
lazyStore.getBalanceAsync(takerAssetData, makerAddress),
|
||||
lazyStore.getBalanceAsync(makerFeeAssetData, makerAddress),
|
||||
lazyStore.getBalanceAsync(takerFeeAssetData, makerAddress),
|
||||
lazyStore.getProxyAllowanceAsync(makerFeeAssetData, makerAddress),
|
||||
lazyStore.getBalanceAsync(takerAssetData, this.takerAddress),
|
||||
lazyStore.getProxyAllowanceAsync(takerAssetData, this.takerAddress),
|
||||
lazyStore.getBalanceAsync(makerAssetData, this.takerAddress),
|
||||
lazyStore.getBalanceAsync(makerFeeAssetData, this.takerAddress),
|
||||
lazyStore.getBalanceAsync(takerFeeAssetData, this.takerAddress),
|
||||
lazyStore.getProxyAllowanceAsync(takerFeeAssetData, this.takerAddress),
|
||||
lazyStore.getBalanceAsync(makerFeeAssetData, feeRecipient),
|
||||
lazyStore.getBalanceAsync(takerFeeAssetData, feeRecipient),
|
||||
]);
|
||||
|
||||
const expFilledTakerAmount = expectedFillResults.takerAssetFilledAmount;
|
||||
const expFilledMakerAmount = expectedFillResults.makerAssetFilledAmount;
|
||||
const expMakerFeePaid = expectedFillResults.makerFeePaid;
|
||||
@@ -517,7 +597,40 @@ export class FillOrderCombinatorialUtils {
|
||||
});
|
||||
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const actFilledTakerAmount = await this.exchangeWrapper.getTakerAssetFilledAmountAsync(orderHash);
|
||||
const [
|
||||
actFilledTakerAmount,
|
||||
actMakerAssetBalanceOfMaker,
|
||||
actMakerAssetAllowanceOfMaker,
|
||||
actTakerAssetBalanceOfMaker,
|
||||
actMakerFeeAssetBalanceOfMaker,
|
||||
actMakerFeeAssetAllowanceOfMaker,
|
||||
actTakerFeeAssetBalanceOfMaker,
|
||||
actTakerAssetBalanceOfTaker,
|
||||
actTakerAssetAllowanceOfTaker,
|
||||
actMakerAssetBalanceOfTaker,
|
||||
actMakerFeeAssetBalanceOfTaker,
|
||||
actTakerFeeAssetBalanceOfTaker,
|
||||
actTakerFeeAssetAllowanceOfTaker,
|
||||
actMakerFeeAssetBalanceOfFeeRecipient,
|
||||
actTakerFeeAssetBalanceOfFeeRecipient,
|
||||
] = await Promise.all([
|
||||
this.exchangeWrapper.getTakerAssetFilledAmountAsync(orderHash),
|
||||
this.assetWrapper.getBalanceAsync(makerAddress, makerAssetData),
|
||||
this.assetWrapper.getProxyAllowanceAsync(makerAddress, makerAssetData),
|
||||
this.assetWrapper.getBalanceAsync(makerAddress, takerAssetData),
|
||||
this.assetWrapper.getBalanceAsync(makerAddress, makerFeeAssetData),
|
||||
this.assetWrapper.getProxyAllowanceAsync(makerAddress, makerFeeAssetData),
|
||||
this.assetWrapper.getBalanceAsync(makerAddress, takerFeeAssetData),
|
||||
this.assetWrapper.getBalanceAsync(this.takerAddress, takerAssetData),
|
||||
this.assetWrapper.getProxyAllowanceAsync(this.takerAddress, takerAssetData),
|
||||
this.assetWrapper.getBalanceAsync(this.takerAddress, makerAssetData),
|
||||
this.assetWrapper.getBalanceAsync(this.takerAddress, makerFeeAssetData),
|
||||
this.assetWrapper.getBalanceAsync(this.takerAddress, takerFeeAssetData),
|
||||
this.assetWrapper.getProxyAllowanceAsync(this.takerAddress, takerFeeAssetData),
|
||||
this.assetWrapper.getBalanceAsync(feeRecipient, makerFeeAssetData),
|
||||
this.assetWrapper.getBalanceAsync(feeRecipient, takerFeeAssetData),
|
||||
]);
|
||||
|
||||
expect(actFilledTakerAmount, 'filledTakerAmount').to.be.bignumber.equal(expFilledTakerAmount);
|
||||
|
||||
const exchangeLogs = _.filter(
|
||||
@@ -542,105 +655,52 @@ export class FillOrderCombinatorialUtils {
|
||||
expect(log.args.makerAssetData, 'log.args.makerAssetData').to.be.equal(makerAssetData);
|
||||
expect(log.args.takerAssetData, 'log.args.takerAssetData').to.be.equal(takerAssetData);
|
||||
|
||||
const actMakerAssetBalanceOfMaker = await this.assetWrapper.getBalanceAsync(makerAddress, makerAssetData);
|
||||
expect(actMakerAssetBalanceOfMaker, 'makerAssetBalanceOfMaker').to.be.bignumber.equal(
|
||||
expMakerAssetBalanceOfMaker,
|
||||
);
|
||||
|
||||
const actMakerAssetAllowanceOfMaker = await this.assetWrapper.getProxyAllowanceAsync(
|
||||
makerAddress,
|
||||
makerAssetData,
|
||||
);
|
||||
expect(actMakerAssetAllowanceOfMaker, 'makerAssetAllowanceOfMaker').to.be.bignumber.equal(
|
||||
expMakerAssetAllowanceOfMaker,
|
||||
);
|
||||
|
||||
const actTakerAssetBalanceOfMaker = await this.assetWrapper.getBalanceAsync(makerAddress, takerAssetData);
|
||||
expect(actTakerAssetBalanceOfMaker, 'takerAssetBalanceOfMaker').to.be.bignumber.equal(
|
||||
expTakerAssetBalanceOfMaker,
|
||||
);
|
||||
|
||||
const actMakerFeeAssetBalanceOfMaker = await this.assetWrapper.getBalanceAsync(makerAddress, makerFeeAssetData);
|
||||
expect(actMakerFeeAssetBalanceOfMaker, 'makerFeeAssetBalanceOfMaker').to.be.bignumber.equal(
|
||||
expMakerFeeAssetBalanceOfMaker,
|
||||
);
|
||||
|
||||
const actMakerFeeAssetAllowanceOfMaker = await this.assetWrapper.getProxyAllowanceAsync(
|
||||
makerAddress,
|
||||
makerFeeAssetData,
|
||||
);
|
||||
expect(actMakerFeeAssetAllowanceOfMaker, 'makerFeeAssetAllowanceOfMaker').to.be.bignumber.equal(
|
||||
expMakerFeeAssetAllowanceOfMaker,
|
||||
);
|
||||
|
||||
const actTakerFeeAssetBalanceOfMaker = await this.assetWrapper.getBalanceAsync(makerAddress, takerFeeAssetData);
|
||||
expect(actTakerFeeAssetBalanceOfMaker, 'takerFeeAssetBalanceOfMaker').to.be.bignumber.equal(
|
||||
expTakerFeeAssetBalanceOfMaker,
|
||||
);
|
||||
|
||||
const actTakerAssetBalanceOfTaker = await this.assetWrapper.getBalanceAsync(this.takerAddress, takerAssetData);
|
||||
expect(actTakerAssetBalanceOfTaker, 'TakerAssetBalanceOfTaker').to.be.bignumber.equal(
|
||||
expTakerAssetBalanceOfTaker,
|
||||
);
|
||||
|
||||
const actTakerAssetAllowanceOfTaker = await this.assetWrapper.getProxyAllowanceAsync(
|
||||
this.takerAddress,
|
||||
takerAssetData,
|
||||
);
|
||||
|
||||
expect(actTakerAssetAllowanceOfTaker, 'takerAssetAllowanceOfTaker').to.be.bignumber.equal(
|
||||
expTakerAssetAllowanceOfTaker,
|
||||
);
|
||||
|
||||
const actMakerAssetBalanceOfTaker = await this.assetWrapper.getBalanceAsync(this.takerAddress, makerAssetData);
|
||||
expect(actMakerAssetBalanceOfTaker, 'makerAssetBalanceOfTaker').to.be.bignumber.equal(
|
||||
expMakerAssetBalanceOfTaker,
|
||||
);
|
||||
|
||||
const actMakerFeeAssetBalanceOfTaker = await this.assetWrapper.getBalanceAsync(
|
||||
this.takerAddress,
|
||||
makerFeeAssetData,
|
||||
);
|
||||
expect(actMakerFeeAssetBalanceOfTaker, 'makerFeeAssetBalanceOfTaker').to.be.bignumber.equal(
|
||||
expMakerFeeAssetBalanceOfTaker,
|
||||
);
|
||||
|
||||
const actTakerFeeAssetBalanceOfTaker = await this.assetWrapper.getBalanceAsync(
|
||||
this.takerAddress,
|
||||
takerFeeAssetData,
|
||||
);
|
||||
expect(actTakerFeeAssetBalanceOfTaker, 'takerFeeAssetBalanceOfTaker').to.be.bignumber.equal(
|
||||
expTakerFeeAssetBalanceOfTaker,
|
||||
);
|
||||
|
||||
const actTakerFeeAssetAllowanceOfTaker = await this.assetWrapper.getProxyAllowanceAsync(
|
||||
this.takerAddress,
|
||||
takerFeeAssetData,
|
||||
);
|
||||
expect(actTakerFeeAssetAllowanceOfTaker, 'takerFeeAssetAllowanceOfTaker').to.be.bignumber.equal(
|
||||
expTakerFeeAssetAllowanceOfTaker,
|
||||
);
|
||||
|
||||
const actMakerFeeAssetBalanceOfFeeRecipient = await this.assetWrapper.getBalanceAsync(
|
||||
feeRecipient,
|
||||
makerFeeAssetData,
|
||||
);
|
||||
expect(actMakerFeeAssetBalanceOfFeeRecipient, 'makerFeeAssetBalanceOfFeeRecipient').to.be.bignumber.equal(
|
||||
expMakerFeeAssetBalanceOfFeeRecipient,
|
||||
);
|
||||
|
||||
const actTakerFeeAssetBalanceOfFeeRecipient = await this.assetWrapper.getBalanceAsync(
|
||||
feeRecipient,
|
||||
takerFeeAssetData,
|
||||
);
|
||||
expect(actTakerFeeAssetBalanceOfFeeRecipient, 'takerFeeAssetBalanceOfFeeRecipient').to.be.bignumber.equal(
|
||||
expTakerFeeAssetBalanceOfFeeRecipient,
|
||||
);
|
||||
}
|
||||
|
||||
private async _modifyTraderStateAsync(
|
||||
makerStateScenario: TraderStateScenario,
|
||||
takerStateScenario: TraderStateScenario,
|
||||
fillScenario: FillScenario,
|
||||
signedOrder: SignedOrder,
|
||||
takerAssetFillAmount: BigNumber,
|
||||
): Promise<void> {
|
||||
@@ -663,7 +723,7 @@ export class FillOrderCombinatorialUtils {
|
||||
);
|
||||
|
||||
let makerAssetBalance;
|
||||
switch (makerStateScenario.traderAssetBalance) {
|
||||
switch (fillScenario.makerStateScenario.traderAssetBalance) {
|
||||
case BalanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -685,11 +745,11 @@ export class FillOrderCombinatorialUtils {
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'makerStateScenario.traderAssetBalance',
|
||||
makerStateScenario.traderAssetBalance,
|
||||
fillScenario.makerStateScenario.traderAssetBalance,
|
||||
);
|
||||
}
|
||||
if (makerAssetBalance !== undefined) {
|
||||
await this.assetWrapper.setBalanceAsync(
|
||||
await this.assetWrapper.setUnscaledBalanceAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.makerAssetData,
|
||||
makerAssetBalance,
|
||||
@@ -697,7 +757,7 @@ export class FillOrderCombinatorialUtils {
|
||||
}
|
||||
|
||||
let takerAssetBalance;
|
||||
switch (takerStateScenario.traderAssetBalance) {
|
||||
switch (fillScenario.takerStateScenario.traderAssetBalance) {
|
||||
case BalanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -719,15 +779,21 @@ export class FillOrderCombinatorialUtils {
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'takerStateScenario.traderAssetBalance',
|
||||
takerStateScenario.traderAssetBalance,
|
||||
fillScenario.takerStateScenario.traderAssetBalance,
|
||||
);
|
||||
}
|
||||
if (takerAssetBalance !== undefined) {
|
||||
await this.assetWrapper.setBalanceAsync(this.takerAddress, signedOrder.takerAssetData, takerAssetBalance);
|
||||
await this.assetWrapper.setUnscaledBalanceAsync(
|
||||
this.takerAddress,
|
||||
signedOrder.takerAssetData,
|
||||
takerAssetBalance,
|
||||
);
|
||||
}
|
||||
|
||||
const isMakerFeeAssetMakerAsset =
|
||||
fillScenario.orderScenario.makerFeeAssetDataScenario === FeeAssetDataScenario.MakerToken;
|
||||
let makerFeeBalance;
|
||||
switch (makerStateScenario.feeBalance) {
|
||||
switch (fillScenario.makerStateScenario.feeBalance) {
|
||||
case BalanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -747,18 +813,23 @@ export class FillOrderCombinatorialUtils {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('makerStateScenario.feeBalance', makerStateScenario.feeBalance);
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'makerStateScenario.feeBalance',
|
||||
fillScenario.makerStateScenario.feeBalance,
|
||||
);
|
||||
}
|
||||
if (makerFeeBalance !== undefined) {
|
||||
await this.assetWrapper.setBalanceAsync(
|
||||
if (isMakerFeeAssetMakerAsset && makerFeeBalance !== undefined) {
|
||||
await this.assetWrapper.setUnscaledBalanceAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.makerFeeAssetData,
|
||||
makerFeeBalance,
|
||||
);
|
||||
}
|
||||
|
||||
const isTakerFeeAssetTakerAsset =
|
||||
fillScenario.orderScenario.takerFeeAssetDataScenario === FeeAssetDataScenario.TakerToken;
|
||||
let takerFeeBalance;
|
||||
switch (takerStateScenario.feeBalance) {
|
||||
switch (fillScenario.takerStateScenario.feeBalance) {
|
||||
case BalanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -778,14 +849,21 @@ export class FillOrderCombinatorialUtils {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('takerStateScenario.feeBalance', takerStateScenario.feeBalance);
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'takerStateScenario.feeBalance',
|
||||
fillScenario.takerStateScenario.feeBalance,
|
||||
);
|
||||
}
|
||||
if (takerFeeBalance !== undefined) {
|
||||
await this.assetWrapper.setBalanceAsync(this.takerAddress, signedOrder.takerFeeAssetData, takerFeeBalance);
|
||||
if (isTakerFeeAssetTakerAsset && takerFeeBalance !== undefined) {
|
||||
await this.assetWrapper.setUnscaledBalanceAsync(
|
||||
this.takerAddress,
|
||||
signedOrder.takerFeeAssetData,
|
||||
takerFeeBalance,
|
||||
);
|
||||
}
|
||||
|
||||
let makerAssetAllowance;
|
||||
switch (makerStateScenario.traderAssetAllowance) {
|
||||
switch (fillScenario.makerStateScenario.traderAssetAllowance) {
|
||||
case AllowanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -808,7 +886,7 @@ export class FillOrderCombinatorialUtils {
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'makerStateScenario.traderAssetAllowance',
|
||||
makerStateScenario.traderAssetAllowance,
|
||||
fillScenario.makerStateScenario.traderAssetAllowance,
|
||||
);
|
||||
}
|
||||
if (makerAssetAllowance !== undefined) {
|
||||
@@ -820,7 +898,7 @@ export class FillOrderCombinatorialUtils {
|
||||
}
|
||||
|
||||
let takerAssetAllowance;
|
||||
switch (takerStateScenario.traderAssetAllowance) {
|
||||
switch (fillScenario.takerStateScenario.traderAssetAllowance) {
|
||||
case AllowanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -843,7 +921,7 @@ export class FillOrderCombinatorialUtils {
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'takerStateScenario.traderAssetAllowance',
|
||||
takerStateScenario.traderAssetAllowance,
|
||||
fillScenario.takerStateScenario.traderAssetAllowance,
|
||||
);
|
||||
}
|
||||
if (takerAssetAllowance !== undefined) {
|
||||
@@ -855,7 +933,7 @@ export class FillOrderCombinatorialUtils {
|
||||
}
|
||||
|
||||
let makerFeeAllowance;
|
||||
switch (makerStateScenario.feeAllowance) {
|
||||
switch (fillScenario.makerStateScenario.feeAllowance) {
|
||||
case AllowanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -876,9 +954,12 @@ export class FillOrderCombinatorialUtils {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('makerStateScenario.feeAllowance', makerStateScenario.feeAllowance);
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'makerStateScenario.feeAllowance',
|
||||
fillScenario.makerStateScenario.feeAllowance,
|
||||
);
|
||||
}
|
||||
if (makerFeeAllowance !== undefined) {
|
||||
if (isMakerFeeAssetMakerAsset && makerFeeAllowance !== undefined) {
|
||||
await this.assetWrapper.setProxyAllowanceAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.makerFeeAssetData,
|
||||
@@ -887,7 +968,7 @@ export class FillOrderCombinatorialUtils {
|
||||
}
|
||||
|
||||
let takerFeeAllowance;
|
||||
switch (takerStateScenario.feeAllowance) {
|
||||
switch (fillScenario.takerStateScenario.feeAllowance) {
|
||||
case AllowanceAmountScenario.Higher:
|
||||
break; // Noop since this is already the default
|
||||
|
||||
@@ -908,9 +989,12 @@ export class FillOrderCombinatorialUtils {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('takerStateScenario.feeAllowance', takerStateScenario.feeAllowance);
|
||||
throw errorUtils.spawnSwitchErr(
|
||||
'takerStateScenario.feeAllowance',
|
||||
fillScenario.takerStateScenario.feeAllowance,
|
||||
);
|
||||
}
|
||||
if (takerFeeAllowance !== undefined) {
|
||||
if (isTakerFeeAssetTakerAsset && takerFeeAllowance !== undefined) {
|
||||
await this.assetWrapper.setProxyAllowanceAsync(
|
||||
this.takerAddress,
|
||||
signedOrder.takerFeeAssetData,
|
||||
@@ -920,12 +1004,9 @@ export class FillOrderCombinatorialUtils {
|
||||
}
|
||||
}
|
||||
|
||||
function getTakerAssetFillAmountAsync(
|
||||
signedOrder: SignedOrder,
|
||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario,
|
||||
): BigNumber {
|
||||
function getTakerAssetFillAmount(signedOrder: SignedOrder, fillScenario: FillScenario): BigNumber {
|
||||
let takerAssetFillAmount;
|
||||
switch (takerAssetFillAmountScenario) {
|
||||
switch (fillScenario.takerAssetFillAmountScenario) {
|
||||
case TakerAssetFillAmountScenario.Zero:
|
||||
takerAssetFillAmount = new BigNumber(0);
|
||||
break;
|
||||
@@ -939,20 +1020,42 @@ function getTakerAssetFillAmountAsync(
|
||||
break;
|
||||
|
||||
case TakerAssetFillAmountScenario.LessThanTakerAssetAmount:
|
||||
const takerAssetProxyId = assetDataUtils.decodeAssetProxyId(signedOrder.takerAssetData);
|
||||
const makerAssetProxyId = assetDataUtils.decodeAssetProxyId(signedOrder.makerAssetData);
|
||||
const isEitherAssetERC721 =
|
||||
takerAssetProxyId === AssetProxyId.ERC721 || makerAssetProxyId === AssetProxyId.ERC721;
|
||||
if (isEitherAssetERC721) {
|
||||
throw new Error(
|
||||
'Cannot test `TakerAssetFillAmountScenario.LessThanTakerAssetAmount` together with ERC721 assets since orders involving ERC721 must always be filled exactly.',
|
||||
);
|
||||
}
|
||||
// TODO(dorothy-zbornak): Do we need this?
|
||||
// const {
|
||||
// makerAssetDataScenario,
|
||||
// takerAssetDataScenario,
|
||||
// makerFeeAssetDataScenario,
|
||||
// takerFeeAssetDataScenario,
|
||||
// } = fillScenario.orderScenario;
|
||||
// const NFT_SCENARIOS = [
|
||||
// AssetDataScenario.ERC721,
|
||||
// AssetDataScenario.ERC1155NonFungible,
|
||||
// ];
|
||||
// const FEE_NFT_SCENARIOS = [
|
||||
// FeeAssetDataScenario.ERC721,
|
||||
// FeeAssetDataScenario.ERC1155NonFungible,
|
||||
// ];
|
||||
// if (_.includes(NFT_SCENARIOS, makerAssetDataScenario)) {
|
||||
// FEE_NFT_SCENARIOS.push(FeeAssetDataScenario.MakerToken);
|
||||
// }
|
||||
// if (_.includes(NFT_SCENARIOS, takerAssetDataScenario)) {
|
||||
// FEE_NFT_SCENARIOS.push(FeeAssetDataScenario.TakerToken);
|
||||
// }
|
||||
// const isAnyAssetNonFungible =
|
||||
// _.includes(NFT_SCENARIOS, makerAssetDataScenario) ||
|
||||
// _.includes(NFT_SCENARIOS, takerAssetDataScenario) ||
|
||||
// _.includes(FEE_NFT_SCENARIOS, makerFeeAssetDataScenario) ||
|
||||
// _.includes(FEE_NFT_SCENARIOS, takerFeeAssetDataScenario);
|
||||
// if (isAnyAssetNonFungible) {
|
||||
// throw new Error(
|
||||
// 'Cannot test `TakerAssetFillAmountScenario.LessThanTakerAssetAmount` together with ERC721 assets since orders involving ERC721 must always be filled exactly.',
|
||||
// );
|
||||
// }
|
||||
takerAssetFillAmount = signedOrder.takerAssetAmount.div(2).integerValue(BigNumber.ROUND_FLOOR);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('TakerAssetFillAmountScenario', takerAssetFillAmountScenario);
|
||||
throw errorUtils.spawnSwitchErr('TakerAssetFillAmountScenario', fillScenario.takerAssetFillAmountScenario);
|
||||
}
|
||||
|
||||
return takerAssetFillAmount;
|
||||
@@ -971,11 +1074,7 @@ function fillErrorToRevertError(order: Order, error: FillOrderError): RevertErro
|
||||
case FillOrderError.InvalidFillPrice:
|
||||
return new ExchangeRevertErrors.FillError(ExchangeRevertErrors.FillErrorCode.InvalidFillPrice, orderHash);
|
||||
case FillOrderError.TransferFailed:
|
||||
return new ExchangeRevertErrors.AssetProxyTransferError(
|
||||
orderHash,
|
||||
undefined,
|
||||
new StringRevertError(FillOrderError.TransferFailed).encode(),
|
||||
);
|
||||
return new ExchangeRevertErrors.AssetProxyTransferError(orderHash);
|
||||
default:
|
||||
return new StringRevertError(error);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ export enum AssetDataScenario {
|
||||
ERC20FiveDecimals = 'ERC20_FIVE_DECIMALS',
|
||||
ERC20EighteenDecimals = 'ERC20_EIGHTEEN_DECIMALS',
|
||||
ERC721 = 'ERC721',
|
||||
ERC1155Fungible = 'ERC1155_FUNGIBLE',
|
||||
ERC1155NonFungible = 'ERC1155_NON_FUNGIBLE',
|
||||
MultiAssetERC20 = 'MULTI_ASSET_ERC20',
|
||||
}
|
||||
|
||||
export enum FeeAssetDataScenario {
|
||||
@@ -34,6 +37,9 @@ export enum FeeAssetDataScenario {
|
||||
ERC20FiveDecimals = 'ERC20_FIVE_DECIMALS',
|
||||
ERC20EighteenDecimals = 'ERC20_EIGHTEEN_DECIMALS',
|
||||
ERC721 = 'ERC721',
|
||||
ERC1155Fungible = 'ERC1155_FUNGIBLE',
|
||||
ERC1155NonFungible = 'ERC1155_NON_FUNGIBLE',
|
||||
MultiAssetERC20 = 'MULTI_ASSET_ERC20',
|
||||
MakerToken = 'MAKER_TOKEN',
|
||||
TakerToken = 'TAKER_TOKEN',
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { constants, ERC721TokenIdsByOwner } from '@0x/contracts-test-utils';
|
||||
import { constants, ERC1155HoldingsByOwner, ERC721TokenIdsByOwner } from '@0x/contracts-test-utils';
|
||||
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
|
||||
import { Order } from '@0x/types';
|
||||
import { BigNumber, errorUtils } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
AssetDataScenario,
|
||||
@@ -17,13 +17,16 @@ import {
|
||||
const TEN_UNITS_EIGHTEEN_DECIMALS = new BigNumber('10e18');
|
||||
const FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber('5e18');
|
||||
const POINT_ONE_UNITS_EIGHTEEN_DECIMALS = new BigNumber('0.1e18');
|
||||
const ONE_UNITS_EIGHTEEN_DECIMALS = new BigNumber('1e18');
|
||||
const POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber('0.05e18');
|
||||
const TEN_UNITS_FIVE_DECIMALS = new BigNumber('10e5');
|
||||
const FIVE_UNITS_FIVE_DECIMALS = new BigNumber('5e5');
|
||||
const POINT_ONE_UNITS_FIVE_DECIMALS = new BigNumber('0.1e5');
|
||||
const ONE_UNITS_FIVE_DECIMALS = new BigNumber('1e5');
|
||||
const POINT_ZERO_FIVE_UNITS_FIVE_DECIMALS = new BigNumber('0.05e5');
|
||||
const TEN_UNITS_ZERO_DECIMALS = new BigNumber(10);
|
||||
const ONE_THOUSAND_UNITS_ZERO_DECIMALS = new BigNumber(1000);
|
||||
const TEN_UNITS_ZERO_DECIMALS = new BigNumber(10);
|
||||
const FIVE_UNITS_ZERO_DECIMALS = new BigNumber(5);
|
||||
const ONE_UNITS_ZERO_DECIMALS = new BigNumber(1);
|
||||
const ONE_NFT_UNIT = new BigNumber(1);
|
||||
const ZERO_UNITS = new BigNumber(0);
|
||||
@@ -33,8 +36,10 @@ export class OrderFactoryFromScenario {
|
||||
private readonly _erc20EighteenDecimalTokenAddresses: string[];
|
||||
private readonly _erc20FiveDecimalTokenAddresses: string[];
|
||||
private readonly _erc20ZeroDecimalTokenAddresses: string[];
|
||||
private readonly _erc721Token: DummyERC721TokenContract;
|
||||
private readonly _erc721TokenAddress: string;
|
||||
private readonly _erc1155TokenAddress: string;
|
||||
private readonly _erc721Balances: ERC721TokenIdsByOwner;
|
||||
private readonly _erc1155Holdings: ERC1155HoldingsByOwner;
|
||||
private readonly _exchangeAddress: string;
|
||||
private readonly _chainId: number;
|
||||
constructor(
|
||||
@@ -42,8 +47,10 @@ export class OrderFactoryFromScenario {
|
||||
erc20EighteenDecimalTokenAddresses: string[],
|
||||
erc20FiveDecimalTokenAddresses: string[],
|
||||
erc20ZeroDecimalTokenAddresses: string[],
|
||||
erc721Token: DummyERC721TokenContract,
|
||||
erc721TokenAddress: string,
|
||||
erc1155TokenAddress: string,
|
||||
erc721Balances: ERC721TokenIdsByOwner,
|
||||
erc1155Holdings: ERC1155HoldingsByOwner,
|
||||
exchangeAddress: string,
|
||||
chainId: number,
|
||||
) {
|
||||
@@ -51,16 +58,31 @@ export class OrderFactoryFromScenario {
|
||||
this._erc20EighteenDecimalTokenAddresses = erc20EighteenDecimalTokenAddresses;
|
||||
this._erc20FiveDecimalTokenAddresses = erc20FiveDecimalTokenAddresses;
|
||||
this._erc20ZeroDecimalTokenAddresses = erc20ZeroDecimalTokenAddresses;
|
||||
this._erc721Token = erc721Token;
|
||||
this._erc721TokenAddress = erc721TokenAddress;
|
||||
this._erc1155TokenAddress = erc1155TokenAddress;
|
||||
this._erc721Balances = erc721Balances;
|
||||
this._erc1155Holdings = erc1155Holdings;
|
||||
this._exchangeAddress = exchangeAddress;
|
||||
this._chainId = chainId;
|
||||
}
|
||||
public generateOrder(orderScenario: OrderScenario): Order {
|
||||
const makerAddress = this._userAddresses[1];
|
||||
let takerAddress = this._userAddresses[2];
|
||||
const erc721MakerAssetIds = this._erc721Balances[makerAddress][this._erc721Token.address];
|
||||
const erc721TakerAssetIds = this._erc721Balances[takerAddress][this._erc721Token.address];
|
||||
const erc721MakerAssetIds = this._erc721Balances[makerAddress][this._erc721TokenAddress];
|
||||
const erc721TakerAssetIds = this._erc721Balances[takerAddress][this._erc721TokenAddress];
|
||||
const erc1155FungibleMakerTokenIds = getERC1155FungibleOwnerTokenIds(
|
||||
this._erc1155Holdings.fungible[makerAddress][this._erc1155TokenAddress],
|
||||
);
|
||||
const erc1155NonFungibleMakerTokenIds = getERC1155NonFungibleOwnerTokenIds(
|
||||
this._erc1155Holdings.nonFungible[makerAddress][this._erc1155TokenAddress],
|
||||
);
|
||||
const erc1155FungibleTakerTokenIds = getERC1155FungibleOwnerTokenIds(
|
||||
this._erc1155Holdings.fungible[takerAddress][this._erc1155TokenAddress],
|
||||
);
|
||||
const erc1155NonFungibleTakerTokenIds = getERC1155NonFungibleOwnerTokenIds(
|
||||
this._erc1155Holdings.nonFungible[takerAddress][this._erc1155TokenAddress],
|
||||
);
|
||||
const erc1155CallbackData = constants.NULL_BYTES;
|
||||
let feeRecipientAddress;
|
||||
let makerAssetAmount;
|
||||
let takerAssetAmount;
|
||||
@@ -91,14 +113,36 @@ export class OrderFactoryFromScenario {
|
||||
makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0]);
|
||||
break;
|
||||
case AssetDataScenario.ERC721:
|
||||
makerAssetData = assetDataUtils.encodeERC721AssetData(
|
||||
this._erc721Token.address,
|
||||
erc721MakerAssetIds[0],
|
||||
);
|
||||
makerAssetData = assetDataUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721MakerAssetIds[0]);
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0]);
|
||||
break;
|
||||
case AssetDataScenario.ERC1155Fungible:
|
||||
makerAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||
this._erc1155TokenAddress,
|
||||
[erc1155FungibleMakerTokenIds[0]],
|
||||
[ONE_UNITS_ZERO_DECIMALS],
|
||||
erc1155CallbackData,
|
||||
);
|
||||
break;
|
||||
case AssetDataScenario.ERC1155NonFungible:
|
||||
makerAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||
this._erc1155TokenAddress,
|
||||
[erc1155NonFungibleMakerTokenIds[0]],
|
||||
[ONE_UNITS_ZERO_DECIMALS],
|
||||
erc1155CallbackData,
|
||||
);
|
||||
break;
|
||||
case AssetDataScenario.MultiAssetERC20:
|
||||
makerAssetData = assetDataUtils.encodeMultiAssetData(
|
||||
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
|
||||
[
|
||||
assetDataUtils.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0]),
|
||||
assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0]),
|
||||
],
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
|
||||
}
|
||||
@@ -111,14 +155,36 @@ export class OrderFactoryFromScenario {
|
||||
takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1]);
|
||||
break;
|
||||
case AssetDataScenario.ERC721:
|
||||
takerAssetData = assetDataUtils.encodeERC721AssetData(
|
||||
this._erc721Token.address,
|
||||
erc721TakerAssetIds[0],
|
||||
);
|
||||
takerAssetData = assetDataUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721TakerAssetIds[0]);
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1]);
|
||||
break;
|
||||
case AssetDataScenario.ERC1155Fungible:
|
||||
takerAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||
this._erc1155TokenAddress,
|
||||
[erc1155FungibleTakerTokenIds[1]],
|
||||
[ONE_UNITS_ZERO_DECIMALS],
|
||||
erc1155CallbackData,
|
||||
);
|
||||
break;
|
||||
case AssetDataScenario.ERC1155NonFungible:
|
||||
takerAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||
this._erc1155TokenAddress,
|
||||
[erc1155NonFungibleTakerTokenIds[0]],
|
||||
[ONE_UNITS_ZERO_DECIMALS],
|
||||
erc1155CallbackData,
|
||||
);
|
||||
break;
|
||||
case AssetDataScenario.MultiAssetERC20:
|
||||
takerAssetData = assetDataUtils.encodeMultiAssetData(
|
||||
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
|
||||
[
|
||||
assetDataUtils.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1]),
|
||||
assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1]),
|
||||
],
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
|
||||
}
|
||||
@@ -127,17 +193,22 @@ export class OrderFactoryFromScenario {
|
||||
case OrderAssetAmountScenario.Large:
|
||||
switch (orderScenario.makerAssetDataScenario) {
|
||||
case AssetDataScenario.ERC20EighteenDecimals:
|
||||
case AssetDataScenario.ERC1155Fungible:
|
||||
makerAssetAmount = TEN_UNITS_EIGHTEEN_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC20FiveDecimals:
|
||||
makerAssetAmount = TEN_UNITS_FIVE_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC721:
|
||||
case AssetDataScenario.ERC1155NonFungible:
|
||||
makerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
makerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.MultiAssetERC20:
|
||||
makerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
|
||||
}
|
||||
@@ -145,17 +216,22 @@ export class OrderFactoryFromScenario {
|
||||
case OrderAssetAmountScenario.Small:
|
||||
switch (orderScenario.makerAssetDataScenario) {
|
||||
case AssetDataScenario.ERC20EighteenDecimals:
|
||||
case AssetDataScenario.ERC1155Fungible:
|
||||
makerAssetAmount = FIVE_UNITS_EIGHTEEN_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC20FiveDecimals:
|
||||
makerAssetAmount = FIVE_UNITS_FIVE_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC721:
|
||||
case AssetDataScenario.ERC1155NonFungible:
|
||||
makerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
makerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.MultiAssetERC20:
|
||||
makerAssetAmount = ONE_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
|
||||
}
|
||||
@@ -171,17 +247,22 @@ export class OrderFactoryFromScenario {
|
||||
case OrderAssetAmountScenario.Large:
|
||||
switch (orderScenario.takerAssetDataScenario) {
|
||||
case AssetDataScenario.ERC20EighteenDecimals:
|
||||
case AssetDataScenario.ERC1155Fungible:
|
||||
takerAssetAmount = TEN_UNITS_EIGHTEEN_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC20FiveDecimals:
|
||||
takerAssetAmount = TEN_UNITS_FIVE_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC721:
|
||||
case AssetDataScenario.ERC1155NonFungible:
|
||||
takerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
takerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.MultiAssetERC20:
|
||||
takerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
|
||||
}
|
||||
@@ -189,17 +270,22 @@ export class OrderFactoryFromScenario {
|
||||
case OrderAssetAmountScenario.Small:
|
||||
switch (orderScenario.takerAssetDataScenario) {
|
||||
case AssetDataScenario.ERC20EighteenDecimals:
|
||||
case AssetDataScenario.ERC1155Fungible:
|
||||
takerAssetAmount = FIVE_UNITS_EIGHTEEN_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC20FiveDecimals:
|
||||
takerAssetAmount = FIVE_UNITS_FIVE_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.ERC721:
|
||||
case AssetDataScenario.ERC1155NonFungible:
|
||||
takerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
takerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
case AssetDataScenario.MultiAssetERC20:
|
||||
takerAssetAmount = ONE_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
|
||||
}
|
||||
@@ -218,6 +304,8 @@ export class OrderFactoryFromScenario {
|
||||
erc20FiveDecimalTokenAddress: string,
|
||||
erc20ZeroDecimalTokenAddress: string,
|
||||
erc721AssetId: BigNumber,
|
||||
erc1155FungibleTokenId: BigNumber,
|
||||
erc1155NonFungibleAssetId: BigNumber,
|
||||
): [BigNumber, string] => {
|
||||
const feeAmount = getFeeAmountFromScenario(orderScenario, feeAssetDataScenario, feeAmountScenario);
|
||||
switch (feeAssetDataScenario) {
|
||||
@@ -232,7 +320,38 @@ export class OrderFactoryFromScenario {
|
||||
case FeeAssetDataScenario.ERC20ZeroDecimals:
|
||||
return [feeAmount, assetDataUtils.encodeERC20AssetData(erc20ZeroDecimalTokenAddress)];
|
||||
case FeeAssetDataScenario.ERC721:
|
||||
return [feeAmount, assetDataUtils.encodeERC721AssetData(this._erc721Token.address, erc721AssetId)];
|
||||
return [feeAmount, assetDataUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721AssetId)];
|
||||
case FeeAssetDataScenario.ERC1155Fungible:
|
||||
return [
|
||||
feeAmount,
|
||||
assetDataUtils.encodeERC1155AssetData(
|
||||
this._erc1155TokenAddress,
|
||||
[erc1155FungibleTokenId],
|
||||
[ONE_UNITS_ZERO_DECIMALS],
|
||||
erc1155CallbackData,
|
||||
),
|
||||
];
|
||||
case FeeAssetDataScenario.ERC1155NonFungible:
|
||||
return [
|
||||
feeAmount,
|
||||
assetDataUtils.encodeERC1155AssetData(
|
||||
this._erc1155TokenAddress,
|
||||
[erc1155NonFungibleAssetId],
|
||||
[ONE_UNITS_ZERO_DECIMALS],
|
||||
erc1155CallbackData,
|
||||
),
|
||||
];
|
||||
case FeeAssetDataScenario.MultiAssetERC20:
|
||||
return [
|
||||
feeAmount,
|
||||
assetDataUtils.encodeMultiAssetData(
|
||||
[POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS, POINT_ZERO_FIVE_UNITS_FIVE_DECIMALS],
|
||||
[
|
||||
assetDataUtils.encodeERC20AssetData(erc20EighteenDecimalTokenAddress),
|
||||
assetDataUtils.encodeERC20AssetData(erc20FiveDecimalTokenAddress),
|
||||
],
|
||||
),
|
||||
];
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('FeeAssetDataScenario', feeAssetDataScenario);
|
||||
}
|
||||
@@ -245,6 +364,8 @@ export class OrderFactoryFromScenario {
|
||||
this._erc20FiveDecimalTokenAddresses[2],
|
||||
this._erc20ZeroDecimalTokenAddresses[2],
|
||||
erc721MakerAssetIds[1],
|
||||
erc1155FungibleMakerTokenIds[2],
|
||||
erc1155NonFungibleMakerTokenIds[1],
|
||||
);
|
||||
[takerFee, takerFeeAssetData] = feeFromScenario(
|
||||
orderScenario.takerFeeScenario,
|
||||
@@ -253,6 +374,8 @@ export class OrderFactoryFromScenario {
|
||||
this._erc20FiveDecimalTokenAddresses[3],
|
||||
this._erc20ZeroDecimalTokenAddresses[3],
|
||||
erc721TakerAssetIds[1],
|
||||
erc1155FungibleTakerTokenIds[3],
|
||||
erc1155NonFungibleTakerTokenIds[1],
|
||||
);
|
||||
|
||||
switch (orderScenario.expirationTimeSecondsScenario) {
|
||||
@@ -318,6 +441,7 @@ function getFeeAmountFromScenario(
|
||||
): BigNumber {
|
||||
switch (feeAssetDataScenario) {
|
||||
case FeeAssetDataScenario.ERC721:
|
||||
case FeeAssetDataScenario.ERC1155NonFungible:
|
||||
switch (feeAmountScenario) {
|
||||
case OrderAssetAmountScenario.Zero:
|
||||
return ZERO_UNITS;
|
||||
@@ -349,6 +473,7 @@ function getFeeAmountFromScenario(
|
||||
throw errorUtils.spawnSwitchErr('OrderAssetAmountScenario', feeAmountScenario);
|
||||
}
|
||||
case FeeAssetDataScenario.ERC20EighteenDecimals:
|
||||
case FeeAssetDataScenario.ERC1155Fungible:
|
||||
switch (feeAmountScenario) {
|
||||
case OrderAssetAmountScenario.Zero:
|
||||
return ZERO_UNITS;
|
||||
@@ -359,6 +484,17 @@ function getFeeAmountFromScenario(
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('OrderAssetAmountScenario', feeAmountScenario);
|
||||
}
|
||||
case FeeAssetDataScenario.MultiAssetERC20:
|
||||
switch (feeAmountScenario) {
|
||||
case OrderAssetAmountScenario.Zero:
|
||||
return ZERO_UNITS;
|
||||
case OrderAssetAmountScenario.Small:
|
||||
return ONE_UNITS_ZERO_DECIMALS;
|
||||
case OrderAssetAmountScenario.Large:
|
||||
return FIVE_UNITS_ZERO_DECIMALS;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('OrderAssetAmountScenario', feeAmountScenario);
|
||||
}
|
||||
case FeeAssetDataScenario.MakerToken:
|
||||
return getFeeAmountFromScenario(orderScenario, orderScenario.makerAssetDataScenario, feeAmountScenario);
|
||||
case FeeAssetDataScenario.TakerToken:
|
||||
@@ -367,3 +503,13 @@ function getFeeAmountFromScenario(
|
||||
throw errorUtils.spawnSwitchErr('FeeAssetDataScenario', feeAssetDataScenario);
|
||||
}
|
||||
}
|
||||
|
||||
function getERC1155FungibleOwnerTokenIds(holdings: { [tokenId: string]: BigNumber }): BigNumber[] {
|
||||
return _.keys(holdings).map(id => new BigNumber(id));
|
||||
}
|
||||
|
||||
function getERC1155NonFungibleOwnerTokenIds(holdings: { [tokenId: string]: BigNumber[] }): BigNumber[] {
|
||||
return _.values(holdings).map(group => group[0]);
|
||||
}
|
||||
|
||||
// tslint:disable: max-file-line-count
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { ExchangeWrapper } from './exchange_wrapper';
|
||||
|
||||
export class SimpleOrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {
|
||||
private readonly _exchangeWrapper: ExchangeWrapper;
|
||||
constructor(exchange: ExchangeWrapper) {
|
||||
this._exchangeWrapper = exchange;
|
||||
}
|
||||
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
||||
const filledTakerAmount = new BigNumber(await this._exchangeWrapper.getTakerAssetFilledAmountAsync(orderHash));
|
||||
return filledTakerAmount;
|
||||
}
|
||||
public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const isCancelled = await this._exchangeWrapper.isCancelledAsync(orderHash);
|
||||
const orderEpoch = await this._exchangeWrapper.getOrderEpochAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.senderAddress,
|
||||
);
|
||||
const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt;
|
||||
return isCancelled || isCancelledByOrderEpoch;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user