I am trying to swap the erc721 token for erc20 using the 0x protocol which I deployed on the testnet.
Using the following script to perform the swap:
/**
* Local, Data & Env imports
* Exchange.json (from vendorArtifacts attached with this gist)
* "@0x/contract-artifacts": "^3.15.0"
*/
const addr = require('./deployments.json')
const artifacts = require('@0x/contract-artifacts')
const vendorArtifacts = require('./vendor')
const dotenv = require('dotenv')
/**
* 0x and ethers imports
*
* "ethers": "^5.4.6"
* "@0x/contract-wrappers": "^13.17.6"
* "@0x/subproviders": "^6.6.0"
* "@0x/order-utils": "^10.4.28"
*/
const { providers, Wallet, ContractFactory, Contract, BigNumber } = require('ethers')
const { ContractWrappers } = require('@0x/contract-wrappers')
const { PrivateKeyWalletSubprovider, RPCSubprovider, Web3ProviderEngine } = require('@0x/subproviders')
const OrderUtils = require('@0x/order-utils')
dotenv.config()
/**
* chainID - directly obtaining from connected provider to use relevant deployment addresses
* providerEthers - General Ethers JSON-RPC provider to create maker and taker signer
* wrapper - 0x ContractWrappers object
* makerEthers - Signer object connected to maker's private key
* takerEthers - Signer Object connected to taker's private key
* engineMaker - RPC & maker private key provider for 0x
* engineTaker - RPC & taker private key provider for 0x
*/
let chainId, providerEthers, wrapper
let makerEthers, takerEthers, engineMaker, engineTaker
const main = async () => {
await init()
const exchange = new Contract(addr[chainId].exchange, vendorArtifacts.Exchange.compilerOutput.abi, takerEthers)
const devUtils = new Contract(addr[chainId].devUtils, artifacts.DevUtils.compilerOutput.abi, providerEthers)
const erc20 = await deployERC20(takerEthers)
const erc721 = await deployERC721(makerEthers)
/**
* approving erc20 and erc721 to their specific asset proxies
* @notice proxies are already authorized to exchange v3 contract used above
*/
await approveToProxies(
erc20,
BigNumber.from('1000000000000000000000000000'),
erc721,
1,
addr[chainId]
)
wrapper = new ContractWrappers(engineTaker, {
chainId: chainId
})
/**
* @notice not using BigNumbers in order because will cause error when signing: "does not confront to order schema"
*/
const order = {
makerAddress: process.env.MAKER_FROM_ADDRESS,
takerAddress: process.env.TAKER_FROM_ADDRESS,
senderAddress: process.env.TAKER_FROM_ADDRESS,
feeRecipientAddress: '0x0000000000000000000000000000000000000000',
makerAssetAmount: '1',
takerAssetAmount: '10000000000000',
makerFee: '0',
takerFee: '0',
expirationTimeSeconds: '1947301711',
salt: '510',
makerAssetData: await devUtils.encodeERC721AssetData(erc721.address, BigNumber.from(1)),
takerAssetData: await devUtils.encodeERC20AssetData(erc20.address),
makerFeeAssetData: '0x',
takerFeeAssetData: '0x',
chainId: chainId,
exchangeAddress: addr[chainId].exchange,
}
const sOrder = await OrderUtils.signatureUtils.ecSignOrderAsync(engineMaker, order, process.env.MAKER_FROM_ADDRESS)
const valid = await wrapper.exchange.isValidOrderSignature(order, sOrder.signature).callAsync({
to: addr[chainId].exchange
})
if (valid === true) console.log('- Maker signed order successfully')
const abiEncoded = await wrapper.exchange.fillOrder(order, BigNumber.from('1'), sOrder.signature).getABIEncodedTransactionData()
const output = await exchange.executeTransaction(
['510', '1947301711', '2000000000', process.env.MAKER_FROM_ADDRESS, abiEncoded],
sOrder.signature,
{
gasLimit: 7000000,
gasPrice: 2000000000,
type: 1
}
)
console.log(output)
}
const init = async () => {
engineMaker = new Web3ProviderEngine()
engineMaker.addProvider(new PrivateKeyWalletSubprovider(process.env.MAKER_PRIVATE_KEY))
engineMaker.addProvider(new RPCSubprovider(process.env.RPC));
engineMaker.start();
engineTaker = new Web3ProviderEngine()
engineTaker.addProvider(new PrivateKeyWalletSubprovider(process.env.TAKER_PRIVATE_KEY))
engineTaker.addProvider(new RPCSubprovider(process.env.RPC));
engineTaker.start();
providerEthers = new providers.JsonRpcProvider(process.env.RPC)
chainId = await (await providerEthers.getNetwork()).chainId
makerEthers = new Wallet(process.env.MAKER_PRIVATE_KEY, providerEthers)
takerEthers = new Wallet(process.env.TAKER_PRIVATE_KEY, providerEthers)
console.log('- Providers Initialized Successfully')
}
const deployERC20 = async (signer) => {
const erc20Factory = new ContractFactory(
artifacts.DummyERC20Token.compilerOutput.abi,
artifacts.DummyERC20Token.compilerOutput.evm.bytecode.object,
signer
)
const erc20 = await erc20Factory.deploy(
'Test ERC20',
'TST',
18,
BigNumber.from('1000000000000000000000000000')
)
console.log('- ERC20 deployed successfully')
return erc20
}
const deployERC721 = async (signer) => {
const erc721Factory = new ContractFactory(
artifacts.DummyERC721Token.compilerOutput.abi,
artifacts.DummyERC721Token.compilerOutput.evm.bytecode.object,
signer
)
const erc721 = await erc721Factory.deploy(
'Test ERC721',
'TST'
)
await erc721.mint(signer.address, '1')
console.log('- ERC721 deployed successfully')
return erc721
}
const approveToProxies = async (erc20, amount, erc721, tokenId, addrs) => {
await erc20.approve(addrs.erc20Proxy, amount)
await erc721.approve(addrs.erc721Proxy, tokenId)
console.log('- Approved to proxies successfully')
}
main()
But the transaction is getting reverted each time after using 50k gas (you can check all failed attempts here: https://mumbai.polygonscan.com/address/0xAc63b037242D498483C8ad18A0A71aE56e939C22 , source code is not verified on polygonscan since it is causing trouble because of usage of abi encoder v2 experimental)
I have tried different signature mechansims for signing order (eth_sign, sign typed v3 & v4), tried officially deployed 0x v3 contracts on kovan (https://0x.org/docs/guides/0x-cheat-sheet), changing order parameters, swapping maker and taker, etc.
I have also tried to match my approach with 0x protocol's integrations test to make sure everything is correct.
Here are env & deployment files to reproduce to complete environment: https://gist.github.com/hack3r-0m/71102da691183574222fcb90241a07e8
Any help would be highly appericiated, thanks!