0x exchange v3 調試(執行還原,裡面有更多細節)
我正在嘗試使用我在測試網上部署的 0x 協議將 erc721 令牌交換為 erc20。
使用以下腳本執行交換:
/** * 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()
但是每次使用 50k gas 後,交易都會被恢復(您可以在此處查看所有失敗的嘗試:https ://mumbai.polygonscan.com/address/0xAc63b037242D498483C8ad18A0A71aE56e939C22 ,原始碼未在 polygonscan 上驗證,因為它會因使用而引起麻煩abi 編碼器 v2 實驗版)
我嘗試了不同的簽名機制來簽署訂單(eth_sign,簽署類型為 v3 和 v4),嘗試在 kovan 上正式部署 0x v3 合約(https://0x.org/docs/guides/0x-cheat-sheet),更改訂單參數, 交換 maker 和 taker 等。
我還嘗試將我的方法與 0x 協議的集成測試相匹配,以確保一切正確。
以下是要重現到完整環境的 env 和部署文件:https ://gist.github.com/hack3r-0m/71102da691183574222fcb90241a07e8
任何幫助都會非常感謝,謝謝!
聽起來您只想填寫訂單,但您的程式碼正試圖通過元交易來完成,這就是這樣
executeTransaction()
做的。要通過元交易執行填充,接受者還需要簽署元交易對象,這就是進入
executeTransaction()
.@0x/order-utils
對此也有幫助。要直接填寫訂單,接受者只需呼叫
fillOrder()
交易所合約。您還將fillOrder()
呼叫編碼為太低的接受者資產填充量。我認為您的意思是傳入10000000000000
,而不是,因為由於訂單指定的匯率1
,任何小於maker 資產的10000000000000
四捨五入。0