Added ERC1155Proxy tests when data overlaps values in asset data
This commit is contained in:
parent
7ee19e1306
commit
8bae0b81aa
@ -752,6 +752,7 @@ describe('ERC1155Proxy', () => {
|
|||||||
valuesToTransfer,
|
valuesToTransfer,
|
||||||
receiverCallbackData,
|
receiverCallbackData,
|
||||||
);
|
);
|
||||||
|
// remove the function selector and contract address from check, as these change on each test
|
||||||
const offsetToTokenIds = 74;
|
const offsetToTokenIds = 74;
|
||||||
const assetDataWithoutContractAddress = assetData.substr(offsetToTokenIds);
|
const assetDataWithoutContractAddress = assetData.substr(offsetToTokenIds);
|
||||||
const expectedAssetDataWithoutContractAddress =
|
const expectedAssetDataWithoutContractAddress =
|
||||||
@ -789,6 +790,268 @@ describe('ERC1155Proxy', () => {
|
|||||||
];
|
];
|
||||||
expect(finalBalances).to.be.deep.equal(expectedFinalBalances);
|
expect(finalBalances).to.be.deep.equal(expectedFinalBalances);
|
||||||
});
|
});
|
||||||
|
it('should successfully transfer if token values and data are abi encoded to same entry in calldata', async () => {
|
||||||
|
/**
|
||||||
|
* This test ensures that scaling the values does not simultaneously scale the data.
|
||||||
|
* Note that this test is slightly more contrived than the test above, as asset data must be
|
||||||
|
* intentionally hand-modified to produce this result: a functioning abi encoder will not produce it.
|
||||||
|
*/
|
||||||
|
///// Step 1/5 /////
|
||||||
|
// Create tokens with ids [1, 2, 3, 4] and mint a balance of 4 for the `spender`
|
||||||
|
const tokensToCreate = [new BigNumber(1), new BigNumber(2), new BigNumber(3), new BigNumber(4)];
|
||||||
|
const spenderInitialBalance = new BigNumber(4);
|
||||||
|
const receiverInitialBalance = new BigNumber(0);
|
||||||
|
const tokenUri = '';
|
||||||
|
for (const tokenToCreate of tokensToCreate) {
|
||||||
|
// create token
|
||||||
|
await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync(
|
||||||
|
tokenToCreate,
|
||||||
|
tokenUri,
|
||||||
|
{
|
||||||
|
from: owner,
|
||||||
|
},
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
|
||||||
|
// mint balance for spender
|
||||||
|
await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync(
|
||||||
|
tokenToCreate,
|
||||||
|
[spender],
|
||||||
|
[spenderInitialBalance],
|
||||||
|
{
|
||||||
|
from: owner,
|
||||||
|
},
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
///// Step 2/5 /////
|
||||||
|
// Check balances before transfer
|
||||||
|
const balanceHolders = [
|
||||||
|
spender,
|
||||||
|
spender,
|
||||||
|
spender,
|
||||||
|
spender,
|
||||||
|
receiverContract,
|
||||||
|
receiverContract,
|
||||||
|
receiverContract,
|
||||||
|
receiverContract,
|
||||||
|
];
|
||||||
|
const balanceTokens = tokensToCreate.concat(tokensToCreate);
|
||||||
|
const initialBalances = await erc1155Wrapper.getBalancesAsync(balanceHolders, balanceTokens);
|
||||||
|
const expectedInitialBalances = [
|
||||||
|
spenderInitialBalance, // Token ID 1 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 2 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 3 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 4 / Spender Balance
|
||||||
|
receiverInitialBalance, // Token ID 1 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 2 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 3 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 4 / Receiver Balance
|
||||||
|
];
|
||||||
|
expect(initialBalances).to.be.deep.equal(expectedInitialBalances);
|
||||||
|
///// Step 3/5 /////
|
||||||
|
// Create optimized calldata. We format like the table below.
|
||||||
|
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 // ERC1155 contract address
|
||||||
|
// 0x20 0000000000000000000000000000000000000000000000000000000000000080 // Offset to token IDs
|
||||||
|
// 0x40 00000000000000000000000000000000000000000000000000000000000000e0 // Offset to token values
|
||||||
|
// 0x60 00000000000000000000000000000000000000000000000000000000000000e0 // Offset to data (same as values)
|
||||||
|
// 0x80 0000000000000000000000000000000000000000000000000000000000000002 // Length of token Ids
|
||||||
|
// 0xA0 0000000000000000000000000000000000000000000000000000000000000001 // First Token ID
|
||||||
|
// 0xC0 0000000000000000000000000000000000000000000000000000000000000002 // Second Token ID
|
||||||
|
// 0xE0 0000000000000000000000000000000000000000000000000000000000000002 // Length of values (Length of data)
|
||||||
|
// 0x100 0000000000000000000000000000000000000000000000000000000000000002 // First Value
|
||||||
|
// 0x120 0000000000000000000000000000000000000000000000000000000000000002 // Second Value
|
||||||
|
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
|
||||||
|
const tokensToTransfer = [new BigNumber(1), new BigNumber(2)];
|
||||||
|
const valuesToTransfer = [new BigNumber(2), new BigNumber(2)];
|
||||||
|
const valueMultiplier = new BigNumber(2);
|
||||||
|
// create callback data that is the encoded version of `valuesToTransfer`
|
||||||
|
const generatedAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||||
|
erc1155ContractAddress,
|
||||||
|
tokensToTransfer,
|
||||||
|
valuesToTransfer,
|
||||||
|
receiverCallbackData,
|
||||||
|
);
|
||||||
|
// remove the function selector and contract address from check, as these change on each test
|
||||||
|
const offsetToTokenIds = 74;
|
||||||
|
const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
|
||||||
|
const assetDataParameters =
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002';
|
||||||
|
const assetData = `${assetDataSelectorAndContractAddress}${assetDataParameters}`;
|
||||||
|
///// Step 4/5 /////
|
||||||
|
// Transfer tokens
|
||||||
|
const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
|
||||||
|
spender,
|
||||||
|
receiverContract,
|
||||||
|
erc1155Contract.address,
|
||||||
|
tokensToTransfer,
|
||||||
|
valuesToTransfer,
|
||||||
|
valueMultiplier,
|
||||||
|
receiverCallbackData,
|
||||||
|
authorized,
|
||||||
|
assetData,
|
||||||
|
);
|
||||||
|
// check receiver log ignored extra asset data
|
||||||
|
expect(txReceipt.logs.length).to.be.equal(2);
|
||||||
|
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
|
||||||
|
DummyERC1155ReceiverBatchTokenReceivedEventArgs
|
||||||
|
>;
|
||||||
|
expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
|
||||||
|
expect(receiverLog.args.from).to.be.equal(spender);
|
||||||
|
expect(receiverLog.args.tokenIds.length).to.be.deep.equal(2);
|
||||||
|
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
|
||||||
|
expect(receiverLog.args.tokenIds[1]).to.be.bignumber.equal(tokensToTransfer[1]);
|
||||||
|
expect(receiverLog.args.tokenValues.length).to.be.deep.equal(2);
|
||||||
|
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(valuesToTransfer[0].times(valueMultiplier));
|
||||||
|
expect(receiverLog.args.tokenValues[1]).to.be.bignumber.equal(valuesToTransfer[1].times(valueMultiplier));
|
||||||
|
expect(receiverLog.args.data).to.be.deep.equal('0x0000');
|
||||||
|
///// Step 5/5 /////
|
||||||
|
// Validate final balances
|
||||||
|
const finalBalances = await erc1155Wrapper.getBalancesAsync(balanceHolders, balanceTokens);
|
||||||
|
const expectedAmountsTransferred = _.map(valuesToTransfer, value => {
|
||||||
|
return value.times(valueMultiplier);
|
||||||
|
});
|
||||||
|
const expectedFinalBalances = [
|
||||||
|
spenderInitialBalance.minus(expectedAmountsTransferred[0]), // Token ID 1 / Spender Balance
|
||||||
|
spenderInitialBalance.minus(expectedAmountsTransferred[1]), // Token ID 2 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 3 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 4 / Spender Balance
|
||||||
|
receiverInitialBalance.plus(expectedAmountsTransferred[0]), // Token ID 1 / Receiver Balance
|
||||||
|
receiverInitialBalance.plus(expectedAmountsTransferred[1]), // Token ID 2 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 3 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 4 / Receiver Balance
|
||||||
|
];
|
||||||
|
expect(finalBalances).to.be.deep.equal(expectedFinalBalances);
|
||||||
|
});
|
||||||
|
it('should successfully transfer if token ids, values and data are abi encoded to same entry in calldata', async () => {
|
||||||
|
/**
|
||||||
|
* This test combines the two tests above.
|
||||||
|
* Similar to the test above, the asset data must be manually constructed.
|
||||||
|
*/
|
||||||
|
///// Step 1/5 /////
|
||||||
|
// Create tokens with ids [1, 2, 3, 4] and mint a balance of 4 for the `spender`
|
||||||
|
const tokensToCreate = [new BigNumber(1), new BigNumber(2), new BigNumber(3), new BigNumber(4)];
|
||||||
|
const spenderInitialBalance = new BigNumber(4);
|
||||||
|
const receiverInitialBalance = new BigNumber(0);
|
||||||
|
const tokenUri = '';
|
||||||
|
for (const tokenToCreate of tokensToCreate) {
|
||||||
|
// create token
|
||||||
|
await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync(
|
||||||
|
tokenToCreate,
|
||||||
|
tokenUri,
|
||||||
|
{
|
||||||
|
from: owner,
|
||||||
|
},
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
|
||||||
|
// mint balance for spender
|
||||||
|
await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync(
|
||||||
|
tokenToCreate,
|
||||||
|
[spender],
|
||||||
|
[spenderInitialBalance],
|
||||||
|
{
|
||||||
|
from: owner,
|
||||||
|
},
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
///// Step 2/5 /////
|
||||||
|
// Check balances before transfer
|
||||||
|
const balanceHolders = [
|
||||||
|
spender,
|
||||||
|
spender,
|
||||||
|
spender,
|
||||||
|
spender,
|
||||||
|
receiverContract,
|
||||||
|
receiverContract,
|
||||||
|
receiverContract,
|
||||||
|
receiverContract,
|
||||||
|
];
|
||||||
|
const balanceTokens = tokensToCreate.concat(tokensToCreate);
|
||||||
|
const initialBalances = await erc1155Wrapper.getBalancesAsync(balanceHolders, balanceTokens);
|
||||||
|
const expectedInitialBalances = [
|
||||||
|
spenderInitialBalance, // Token ID 1 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 2 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 3 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 4 / Spender Balance
|
||||||
|
receiverInitialBalance, // Token ID 1 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 2 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 3 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 4 / Receiver Balance
|
||||||
|
];
|
||||||
|
expect(initialBalances).to.be.deep.equal(expectedInitialBalances);
|
||||||
|
///// Step 3/5 /////
|
||||||
|
// Create optimized calldata. We format like the table below.
|
||||||
|
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 // ERC1155 contract address
|
||||||
|
// 0x20 0000000000000000000000000000000000000000000000000000000000000080 // Offset to token IDs
|
||||||
|
// 0x40 0000000000000000000000000000000000000000000000000000000000000080 // Offset to token values
|
||||||
|
// 0x60 0000000000000000000000000000000000000000000000000000000000000080 // Offset to data (same as values)
|
||||||
|
// 0x80 0000000000000000000000000000000000000000000000000000000000000002 // Length of token Ids (Length of values / data)
|
||||||
|
// 0xA0 0000000000000000000000000000000000000000000000000000000000000001 // First Token ID (First Value)
|
||||||
|
// 0xC0 0000000000000000000000000000000000000000000000000000000000000002 // Second Token ID (Second Value)
|
||||||
|
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
|
||||||
|
const tokensToTransfer = [new BigNumber(1), new BigNumber(2)];
|
||||||
|
const valuesToTransfer = [new BigNumber(1), new BigNumber(2)];
|
||||||
|
const valueMultiplier = new BigNumber(2);
|
||||||
|
// create callback data that is the encoded version of `valuesToTransfer`
|
||||||
|
const generatedAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||||
|
erc1155ContractAddress,
|
||||||
|
tokensToTransfer,
|
||||||
|
valuesToTransfer,
|
||||||
|
receiverCallbackData,
|
||||||
|
);
|
||||||
|
// remove the function selector and contract address from check, as these change on each test
|
||||||
|
const offsetToTokenIds = 74;
|
||||||
|
const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
|
||||||
|
const assetDataParameters =
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002';
|
||||||
|
const assetData = `${assetDataSelectorAndContractAddress}${assetDataParameters}`;
|
||||||
|
///// Step 4/5 /////
|
||||||
|
// Transfer tokens
|
||||||
|
const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
|
||||||
|
spender,
|
||||||
|
receiverContract,
|
||||||
|
erc1155Contract.address,
|
||||||
|
tokensToTransfer,
|
||||||
|
valuesToTransfer,
|
||||||
|
valueMultiplier,
|
||||||
|
receiverCallbackData,
|
||||||
|
authorized,
|
||||||
|
assetData,
|
||||||
|
);
|
||||||
|
// check receiver log ignored extra asset data
|
||||||
|
expect(txReceipt.logs.length).to.be.equal(2);
|
||||||
|
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
|
||||||
|
DummyERC1155ReceiverBatchTokenReceivedEventArgs
|
||||||
|
>;
|
||||||
|
expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
|
||||||
|
expect(receiverLog.args.from).to.be.equal(spender);
|
||||||
|
expect(receiverLog.args.tokenIds.length).to.be.deep.equal(2);
|
||||||
|
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
|
||||||
|
expect(receiverLog.args.tokenIds[1]).to.be.bignumber.equal(tokensToTransfer[1]);
|
||||||
|
expect(receiverLog.args.tokenValues.length).to.be.deep.equal(2);
|
||||||
|
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(valuesToTransfer[0].times(valueMultiplier));
|
||||||
|
expect(receiverLog.args.tokenValues[1]).to.be.bignumber.equal(valuesToTransfer[1].times(valueMultiplier));
|
||||||
|
expect(receiverLog.args.data).to.be.deep.equal('0x0000');
|
||||||
|
///// Step 5/5 /////
|
||||||
|
// Validate final balances
|
||||||
|
const finalBalances = await erc1155Wrapper.getBalancesAsync(balanceHolders, balanceTokens);
|
||||||
|
const expectedAmountsTransferred = _.map(valuesToTransfer, value => {
|
||||||
|
return value.times(valueMultiplier);
|
||||||
|
});
|
||||||
|
const expectedFinalBalances = [
|
||||||
|
spenderInitialBalance.minus(expectedAmountsTransferred[0]), // Token ID 1 / Spender Balance
|
||||||
|
spenderInitialBalance.minus(expectedAmountsTransferred[1]), // Token ID 2 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 3 / Spender Balance
|
||||||
|
spenderInitialBalance, // Token ID 4 / Spender Balance
|
||||||
|
receiverInitialBalance.plus(expectedAmountsTransferred[0]), // Token ID 1 / Receiver Balance
|
||||||
|
receiverInitialBalance.plus(expectedAmountsTransferred[1]), // Token ID 2 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 3 / Receiver Balance
|
||||||
|
receiverInitialBalance, // Token ID 4 / Receiver Balance
|
||||||
|
];
|
||||||
|
expect(finalBalances).to.be.deep.equal(expectedFinalBalances);
|
||||||
|
});
|
||||||
it('should transfer nothing if value is zero', async () => {
|
it('should transfer nothing if value is zero', async () => {
|
||||||
// setup test parameters
|
// setup test parameters
|
||||||
const tokenHolders = [spender, receiver];
|
const tokenHolders = [spender, receiver];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user