🏪Example Call Construction - Zora Marketplace

Generating the ICall array using Zora Contracts on Polygon

Overview

The calls parameter required by the Brydge widget is simply a list of the necessary function calls that are executed in order to purchase and transfer any NFT to your customer. These calls should be quite similar to the external calls made to an ERC721 (or ERC1155) exchange protocol in a traditional NFT marketplace, except that Brydge handles the execution internally. To achieve this, we use a simple struct, the ICall, to organize the data. The following example will demonstrate how to create the array of ICalls needed to integrate the Brydge widget into your NFT marketplace.

Setup

For this demonstration, we will define the calls array for a purchase of an ERC721 NFT NFT owned by address seller to address buyer with WETH using Zora's exchange contracts defined below:

const ERC20TransferHelper = '0x909e9efE4D87d1a6018C2065aE642b6D0447bc91';
const ERC721TransferHelper = '0xCe6cEf2A9028e1C3B21647ae3B4251038109f42a';
const asksV1Address = '0x3634e984Ba0373Cfa178986FD19F03ba4dD8E469'

const asksV1 = await hre.ethers.getContractAt('AsksV1_1', asksV1Address);
const moduleManager = await hre.ethers.getContractAt('ZoraModuleManager', '0xCCA379FDF4Beda63c4bB0e2A3179Ae62c8716794');
const weth = await hre.ethers.getContractAt('IERC20', '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619');

We are going to assume that the seller has already created an ask for NFT using Zora's asks module, listing it for price.

Zora

What Is Zora?

Zora is a protocol that allows users to buy, sell, or create and participate in auctions for ERC721 NFTs. The Zora smart contracts are currently deployed on Ethereum Mainnet and Polygon, as well as a handful of corresponding testnets. As stated above, we will be demonstrating how to generate and format the calls necessary for Brydge to execute a purchase of an NFT listed on Zora on behalf of your users.

How It Works

Zora's V3 smart contracts are broken down into the 3 types: modules, the module manager, and transfer helpers.

Modules

Modules are smart contracts that handle specific marketplace actions. The three main modules are the Asks module which allows a seller to list an ERC721 token at a fixed price that can be purchased by any prospective buyer, the Offers module which allows a customer to create an offer for an ERC721 token that can be accepted by the owner, and the ReserveAuctions module which allows a seller to run a reserve auction for their NFT. We will focus specifically on the Asks module in this demonstration.

Module Manager

The module manager is a contract that simply manages which modules have access to a user's ERC721 tokens via approvals. For example, a seller looking to list an NFT for a set price must first approve the Asks module via the module manager with the setApprovalForModule function before they can create the ask.

Transfer Helpers

The ERC20 and ERC721 transfer helpers manage the transferring of the respective token types between the buyer, seller, and Zora itself. A seller must approve the ERC721 transfer helper using the ERC721's approve or setApprovalForAll functions before Zora can sell the token on behalf of the user. A buyer that is purchasing an NFT using an ERC20 token must approve the ERC20 transfer helper for the given currency and amount before Zora can execute the transaction.

Calls

In accordance with Zora's docs, we must define three calls to successfully purchase an NFT with an ERC20 currency and transfer it to buyer:

  1. approve the use of the currency by Zora's ERC20 Transfer Helper contract

  2. approve the Asks 1.1 Module in Zora's Module Manager

  3. call the fillAsk function in Zora's AsksV1_1 contract

NOTE: It is required that the calls array is constructed in order. These calls will be executed sequentially, meaning that the transactions may fail if they are out of order. For example, if calls 2 and 3 are swapped above, the fillAsk method cannot succeed because the Asks module will not be approved by the buyer yet.

All call data need to be encoded with the function selector, so we will use the encodeFunctionData(fragment, [values]) method available in Ethers.js contract interfaces.

Currency Approval

To approve the use of WETH by the ERC20 Transfer Helper we use the approve method from the WETH contract:

const wethApproval = weth.interface.encodeFunctionData('approve', [ERC20TransferHelper, price]);

Module Manager Approval

Next we generate the call data to approve the Asks Module using setApprovalForModule:

const moduleApproval = moduleManager.interface.encodeFunctionData('setApprovalForModule', [asksV1Address, true]);

Fill Ask

Now we generate the call data that will actually purchase the NFT using fillAsk. This method takes in 5 parameters: The NFT address, the token ID number of the specific NFT being purchased, the address of the currency used to purchase, the price of the NFT, and the finder's address (in our example there is no finder or finder's fee, so we set this to the zero address).

const fillNFTAsk = asksV1.interface.encodeFunctionData('fillAsk', [NFT.address, tokenId, weth.address, price, hre.ethers.constants.AddressZero]);

Generating the ICall Array

The final step is to take each call and turn it into an ICall. For each ICall, the _value parameter will simply be 0 because we are not making any calls that require a native currency.

const calls = [
        { _to: weth.address, _value: 0, _calldata: wethApproval },
        { _to: moduleManager.address, _value: 0, _calldata: moduleApproval },
        { _to: asksV1.address, _value: 0, _calldata: fillNFTAsk },
      ];

And that's it! calls can now be passed into the Brydge widget, and your customers can purchase NFTs straight from your marketplace cross-chain and cross-currency!

Last updated