Contract-Deployment

0x exchange v3 調試(執行還原,裡面有更多細節)

  • September 17, 2021

我正在嘗試使用我在測試網上部署的 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

引用自:https://ethereum.stackexchange.com/questions/110090