When I try to fill an order with funds from a contract I get the following generic error:
Error: Transaction: 0x1d3161cd7f318c3b0b28fc34b2c6bca0cbf4efdb3b11fcf7ec3af7c9adfd821b exited with an error (status 0). Reason given: TRANSFER_FAILED. Please check that the transaction: - satisfies all conditions set by Solidity
requirestatements. - does not trigger a Solidityrevertstatement.
I've got the following contract:
pragma solidity >=0.4.24;
Exchange exchange;
EthForERC20Token crowdsale;
WrapERC20Token wrapERC20Token;
constructor(
address _exchangeAddress
)
public
{
// The local 0x exchange intstance
exchange = Exchange(_exchangeAddress);
// Grand unlimited allownace to the exchange contract.
wrapERC20Token = new WrapERC20Token(address(exchange));
}
function fillOrder (
Exchange.Order memory _order,
uint256 _assetFillAmount,
bytes memory _signature
)
public
payable
{
exchange.fillOrder(_order,_assetFillAmount, _signature);
}
function getWrappedERC20Address()
public
view
returns(address) {
return address(wrapERC20Token);
}
I tested and the contract owns enough of the WrappedERC20Token which is just an ERC20 token with the option to pre-approve an address with unlimited allowance.
My 0x order creation is as follows:
const wrappedShareAddress = await contract.getWrappedShareAddress();
const maker = accounts[0];
const makerAssetData = zeroX.assetDataUtils.encodeERC20AssetData(etherToken);
const takerAssetData = zeroX.assetDataUtils.encodeERC20AssetData(wrappedShareAddress);
const contractWrappers = new zeroX.ContractWrappers(providerEngine, { networkId: 50 });
const order = {
exchangeAddress: exchange,
makerAddress: maker.toLowerCase(),
takerAddress: NULL_ADDRESS,
senderAddress: NULL_ADDRESS,
feeRecipientAddress: NULL_ADDRESS,
expirationTimeSeconds: (1581437362).toString(),
salt: zeroX.generatePseudoRandomSalt().toString(),
makerAssetAmount: new zeroX.BigNumber("5e17").toFixed(),
takerAssetAmount: new zeroX.BigNumber("5e17").toFixed(),
makerAssetData,
takerAssetData,
makerFee: new zeroX.BigNumber("0").toFixed(),
takerFee: new zeroX.BigNumber("0").toFixed(),
};
// console.log(order);
// Generate the order hash and sign it
const orderHashHex = zeroX.orderHashUtils.getOrderHashHex(order);
signature = await zeroX.signatureUtils.ecSignHashAsync(providerEngine, orderHashHex, maker);
signedOrder = {...order, signature};
const makerWETHApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
etherToken,
maker,
);
await toTxhash.mineTx(makerWETHApprovalTxHash);
const makerWETHDepositTxHash = await contractWrappers.etherToken.depositAsync(
etherToken,
new zeroX.BigNumber("2e18"),
maker,
);
await toTxhash.mineTx(makerWETHDepositTxHash);
Then I call the smart contract function using:
const res = await contract.fillOrder(
signedOrder,
new zeroX.BigNumber("5e17").toFixed(),
signature,
{from: maker, value: new zeroX.BigNumber("1e18").toFixed()}
);
10 ** 18in Javascript, since it is larger (much larger) than the maximum safe integer. Use"2e18"instead of2 * 10 ** 18, or"5e17"instead of0.5 * 10 ** 18, or"1e18"instead of10 ** 18, etc. If you need to utilize values that are "more complicated", thenrequire("bignumber.js")and useBigNumberobjects wherever needed. You can convert such object to a full-precision string via thetoFixed()function. – goodvibration Feb 12 '19 at 13:49.toString()is redundant in the expression("5e17").toString(), yes? – goodvibration Feb 12 '19 at 13:58newfor the initialization ofwrapERC20Tokenbut not for the initialization ofexchange? Since you have norequireorrevertstatements in your code, this is a good candidate for your transaction failure (later in your code, when you callexchange.fillOrder, for example). – goodvibration Feb 12 '19 at 14:01new zeroX.BigNumber("5e17").toFixed()is"500000000000000000". Although it is different from the string"5e17", when converted back to aBigNumberinstance, they will yield the same object. And when you callfillOrder, this string is eventually converted to such an object. So you may as well use the simplest notation possible, which is"5e17". I meant for you to usetoFixed()when handling a value returned from some contract function, sincetoString()may convert it to scientific notation, and then you might end up "losing some digits". – goodvibration Feb 12 '19 at 14:08newfor the exchange because there already is a 0x exchange contract live on my ganache provider. Should be no need to deploy a brand new one you'd think. – jasper Feb 12 '19 at 15:00exchange.fillOrderfunction – jasper Feb 12 '19 at 15:10