@0x/contract-wrappers: `marketBuyOrdersFillOrKill` incorrect ABI encoding
andr11111 opened this issue · 2 comments
This issues is applicable to all batch- and market- fill methods.
Expected Behavior
contractWrappers.exchange.marketBuyOrdersFillOrKill
should correctly ABI-encode the calldata.
Current Behavior
const tx = await contractWrappers.exchange
.marketBuyOrdersFillOrKill([signedOrder1, signedOrder2], new BigNumber(2), [signedOrder1.signature, signedOrder2.signature])
console.log('getABIEncodedTransactionData', tx.getABIEncodedTransactionData());
The result of the ABI-encoding is 0x8bc8efb3000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000060
, which is not correct and missing all of the orders information.
Trying to send such transaction onchain results in an error.
Steps to Reproduce (for bugs)
truffle exec
script:
const {
RPCSubprovider,
Web3ProviderEngine,
} = require('@0x/subproviders');
const { generatePseudoRandomSalt, Order, orderHashUtils, signatureUtils, SignedOrder, assetDataUtils, orderUtils } = require('@0x/order-utils');
const { ContractWrappers } = require('@0x/contract-wrappers');
const { Web3Wrapper } = require('@0x/web3-wrapper');
const { BigNumber } = require('@0x/utils');
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
module.exports = async function() {
try {
const provider = web3.currentProvider;
// Then use the provider
const chainId = 1337;
const contractWrappers = new ContractWrappers(provider, { chainId });
const web3Wrapper = new Web3Wrapper(provider);
const token1 = { address: '0x1Ff4e2A3330F8a7Eb2de6Cc50f4569cC4fDC77d8' };
const token2 = { address: '0x973E5AFDDE356C2ae5c061FDD056Fb7E2F919b11' };
const addresses = await web3Wrapper.getAvailableAddressesAsync();
const makerAddress = addresses[0];
const takerAddress = addresses[1];
const makerAssetData = await contractWrappers.devUtils.encodeERC20AssetData(token1.address).callAsync();
const takerAssetData = await contractWrappers.devUtils.encodeERC20AssetData(token2.address).callAsync();
const makerAssetAmount = new BigNumber(1);
const takerAssetAmount = new BigNumber(1);
const exchangeAddress = contractWrappers.exchange.address;
const order1 = {
makerAddress, // maker is the first address
takerAddress: NULL_ADDRESS, // taker is open and can be filled by anyone
makerAssetAmount, // The maker asset amount
takerAssetAmount, // The taker asset amount
expirationTimeSeconds: new BigNumber(Math.round(Date.now() / 1000) + 10 * 60), // Time when this order expires
makerFee: new BigNumber(0), // 0 maker fees
takerFee: new BigNumber(0), // 0 taker fees
feeRecipientAddress: NULL_ADDRESS, // No fee recipient
senderAddress: NULL_ADDRESS, // Sender address is open and can be submitted by anyone
salt: generatePseudoRandomSalt(), // Random value to provide uniqueness
makerAssetData,
takerAssetData,
exchangeAddress,
makerFeeAssetData: '0x',
takerFeeAssetData: '0x',
chainId,
};
const order2 = {
makerAddress, // maker is the first address
takerAddress: NULL_ADDRESS, // taker is open and can be filled by anyone
makerAssetAmount, // The maker asset amount
takerAssetAmount, // The taker asset amount
expirationTimeSeconds: new BigNumber(Math.round(Date.now() / 1000) + 10 * 60), // Time when this order expires
makerFee: new BigNumber(0), // 0 maker fees
takerFee: new BigNumber(0), // 0 taker fees
feeRecipientAddress: NULL_ADDRESS, // No fee recipient
senderAddress: NULL_ADDRESS, // Sender address is open and can be submitted by anyone
salt: generatePseudoRandomSalt(), // Random value to provide uniqueness
makerAssetData,
takerAssetData,
exchangeAddress,
makerFeeAssetData: '0x',
takerFeeAssetData: '0x',
chainId,
};
const signedOrder1 = await signatureUtils.ecSignOrderAsync(provider, order1, makerAddress);
const signedOrder2 = await signatureUtils.ecSignOrderAsync(provider, order2, makerAddress);
const tx = await contractWrappers.exchange
.marketBuyOrdersFillOrKill([signedOrder1, signedOrder2], new BigNumber(2), [signedOrder1.signature, signedOrder2.signature])
console.log('getABIEncodedTransactionData', tx.getABIEncodedTransactionData());
} catch(e) {
console.log(e);
}
process.exit();
}
Context
I can successfully call the exchange methods directly using web3:
const plainOrder1 = JSON.parse(JSON.stringify(signedOrder1));
const plainOrder2 = JSON.parse(JSON.stringify(signedOrder2));
const exchange = await IExchange.at(contractWrappers.exchange.address);
const gas = await exchange.marketBuyOrdersFillOrKill.estimateGas([plainOrder1, plainOrder2], 1, [plainOrder1.signature, plainOrder2.signature],
{ from: takerAddress, value: 7000000000000000 });
console.log('estimated gas', gas);
const result = await exchange.marketBuyOrdersFillOrKill([plainOrder1, plainOrder2], 2, [plainOrder1.signature, plainOrder2.signature],
{ from: takerAddress, gas: 6700000, value: 7000000000000000 });
Your Environment
0x dependencies versions:
"@0x/contract-wrappers": "^13.6.3",
"@0x/contracts-erc20": "^3.1.5",
"@0x/contracts-test-utils": "^5.3.2",
"@0x/order-utils": "^10.2.4",
"@0x/subproviders": "^6.0.8",
"@0x/utils": "^5.4.1",
"@0x/web3-wrapper": "^7.0.7",
Network |
---|
1337 |
Using 0x Ganache Docker image https://hub.docker.com/r/0xorg/ganache-cli
Hi @andrei-anisimov, thanks for raising this. I'm having trouble reproducing the bug. The only thing that looks "off" is this line, which doesn't need an await
.
const tx = await contractWrappers.exchange
.marketBuyOrdersFillOrKill([signedOrder1, signedOrder2], new BigNumber(2), [signedOrder1.signature, signedOrder2.signature])
Here's my output from running the code snippet:
0x8bc8efb30000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002000000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a6310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea38429929d1ae9a6bed3a65a231d8e1b1f82df3a10ece926f66050f00210668df3f2e4000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004400000000000000000000000005409ed021d9299bf6814279a6a1411a7e866a6310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea38429ca06e4dc6442d40fa60faf0a6f19fa415635ae6182bdb5cb83aab1019a21e9ec00000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001ff4e2a3330f8a7eb2de6cc50f4569cc4fdc77d8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000973e5afdde356c2ae5c061fdd056fb7e2f919b110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000421babea28cddd87f8be08d75d223c50a5eb36ac957ae6f426aa1847ef95ddb0c2952e027ecc1e50ab7c00afedc5bc03d04eaf9821d77ca12ce459534607f6892e1a0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000421c49e33ff3981f7ec8bc56d394ad9ac98980e6b2bfdf408eb5b434fbc47898d38301727a9d524a572118b0f80ef30e08d7cb5653c9321b591962cf6c339d436dc302000000000000000000000000000000000000000000000000000000000000
I uploaded the repro attempt here, which can be run using yarn && yarn build && yarn test
.
Yes, super weird, I can still consistently reproduce it with your script above. You can find the repo here: https://github.com/andrei-anisimov/0x-market-poc. To run to npm install
and truffle exec 0x-test.js
. The output I'm getting:
**********
0x8bc8efb3000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000060
**********