Some Details About Ergo Auction House

Hi community,

Ergo Auction House is live!

I have started the first auction, everyone is welcomed to place bids and also start new auctions!
The only wallet supported currently is the node’s wallet. Hopefully, soon support for other wallets like Yoroi will be added. I personally will add support for Yoroi when it is ready on Yoroi’s side but contributions are also very welcomed.

For some non-technical aspects, please see the FAQ page of the website. Below are some technical details about the app.

Auction Contract

The auction contract is very similar to the discussion here. A lot of the credit must go to @robert @jasondavies @kushti and @scalahub for their great discussion in that post which led to the current contract and app.

{

  val seller = SELF.R4[Coll[Byte]].get
  val endTime = SELF.R5[Int].get
  val minBidDelta = SELF.R6[Long].get
  val currBidder = SELF.R8[Coll[Byte]].get
  val currBid = SELF.value

  val auctionLogic = if (HEIGHT < endTime) {
     val newSelf = OUTPUTS(0)
     val oldBidRefundBox = OUTPUTS(1)
     val newBid = newSelf.value

     newSelf.tokens(0) == SELF.tokens(0) &&
     newSelf.propositionBytes == SELF.propositionBytes &&
     newBid >= currBid + minBidDelta &&
     oldBidRefundBox.propositionBytes == currBidder &&
     oldBidRefundBox.value >= currBid &&
     newSelf.R4[Coll[Byte]].get == seller &&
     newSelf.R5[Int].get == endTime &&
     newSelf.R6[Long].get == minBidDelta &&
     newSelf.R9[Coll[Byte]] == SELF.R9[Coll[Byte]] &&
     newSelf.R7[Coll[Byte]] == SELF.R7[Coll[Byte]]

  } else {
     val winnerBox = OUTPUTS(0)
     val sellerBox = OUTPUTS(1)
     val feeBox = OUTPUTS(2)
     val dataInput = CONTEXT.dataInputs(0)
     val auctionFee = currBid / dataInput.R4[Int].get
     val feeTo = dataInput.R5[Coll[Byte]].get

     dataInput.tokens(0)._1 == auctionTwinToken &&
     feeBox.value >= auctionFee &&
     feeBox.propositionBytes == feeTo &&
     winnerBox.tokens(0) == SELF.tokens(0) &&
     winnerBox.propositionBytes == currBidder &&
     sellerBox.value >= currBid - auctionFee - maxFee * 2 &&
     sellerBox.propositionBytes == seller
  }
  sigmaProp(auctionLogic)
}

Where auctionTwinToken is “35f2a7b17800bd28e0592559bccbaa65a46d90d592064eb98db0193914abb563” and maxFee is 3000000 nano ERG.

Business Aspect

There is a business aspect behind Ergo Auction House similar to one I have explained here. When some auctioning is over, a small percentage of the final bid (2% currently) will go to the Ergo Auction House’s coordinator.

To elaborate more, the auctionTwinToken specified in the auction’s contract is the business’s token in a quantity of two. One of them is used to represent the data input, the other will be in hands of the business coordinator. One who has access to the second pair can receive the auction’s profit by modifying the data input. Here is the data input’s contract:

{
  val isCoordinator = INPUTS(1).tokens(0)._1 == SELF.tokens(0)._1
  sigmaProp(isCoordinator && SELF.id == INPUTS(0).id)
}

This has some nice implications; For example, The coordinator can auction the second pair of the auctionTwinToken and hence auction the Ergo Auction House’s business.

Some Security Aspects

The server is only being used to serve the app, Ergo Auction House will never send requests/info to the server.

The website is currently being served over HTTP since the node runs over HTTP and browsers don’t allow mixed-contents (HTTPS contexts to use HTTP requests). In order to participate in auctions or start new ones, one needs to have access to her node locally (or some kind of secure private network); Although it is possible to use node through the internet, I strongly advise against doing so.
The app is completely open-sourced and accessible here.

Contributions are welcomed!

6 Likes

The auction’s contract is updated to address an issue. Big thanks to @jasondavies for reporting the bug. The fix is already done and is transparent for users!

2 Likes

To address an issue raised by @kushti:
“I think with strict deadline there’s a good strategy to get a better price: wait until few blocks before the end of an auction and then submit a slightly better price.
So makes sense to prolong deadline for e.g. 30-60 blocks if bid made e.g. <= 10 blocks before the end.”

Here is the modified contract to take into account the time extension feature:

{
  val seller = SELF.R4[Coll[Byte]].get
  val endTime = SELF.R5[Int].get
  val minBidDelta = SELF.R6[Long].get
  val currBidder = SELF.R8[Coll[Byte]].get
  val currBid = SELF.value

  val auctionLogic = if (HEIGHT < endTime) {
     val newSelf = OUTPUTS(0)
     val oldBidRefundBox = OUTPUTS(1)
     val newBid = newSelf.value
     val newEndTime = if (endTime - HEIGHT <= extendThreshold) endTime + extendNum
                      else endTime

     newSelf.tokens(0) == SELF.tokens(0) &&
     newSelf.propositionBytes == SELF.propositionBytes &&
     newBid >= currBid + minBidDelta &&
     oldBidRefundBox.propositionBytes == currBidder &&
     oldBidRefundBox.value >= currBid &&
     newSelf.R4[Coll[Byte]].get == seller &&
     newSelf.R5[Int].get == newEndTime &&
     newSelf.R6[Long].get == minBidDelta &&
     newSelf.R9[Coll[Byte]] == SELF.R9[Coll[Byte]] &&
     newSelf.R7[Coll[Byte]] == SELF.R7[Coll[Byte]]

  } else {
     val winnerBox = OUTPUTS(0)
     val sellerBox = OUTPUTS(1)
     val feeBox = OUTPUTS(2)
     val dataInput = CONTEXT.dataInputs(0)
     val auctionFee = currBid / dataInput.R4[Int].get
     val feeTo = dataInput.R5[Coll[Byte]].get

     dataInput.tokens(0)._1 == auctionTwinToken &&
     feeBox.value >= auctionFee &&
     feeBox.propositionBytes == feeTo &&
     winnerBox.tokens(0) == SELF.tokens(0) &&
     winnerBox.propositionBytes == currBidder &&
     sellerBox.value >= currBid - auctionFee - maxFee * 2 &&
     sellerBox.propositionBytes == seller
  }
  sigmaProp(auctionLogic)
}

Basically, the only change is in the first part of the contract where the R5 register (containing the end block height) must increase when tx is being mined within a threshold. The change is trivial but please audit to prevent potential holes.
I think 15 and 20 for extendThreshold and extendNum respectively are potentially good choices.

Also, since some folks may care about the exact finishing height of their auction (either their auction is too competitive and the raised issue doesn’t happen or the seller just needs the money in time) I’m gonna make the option of whether to have this feature or not available when starting the auction; So basically, the app will support two auction’s contracts.

2 Likes

Ergo Auction House is updated!
It now supports auto extending auction’s duration if enabled:


Also, the update includes some minor UI improvements.

Please make sure the app is not cached by your browser in order to see the new version (use ctrl+shift+R or cmd+shift+R for force refreshing if needed)

4 Likes

Nice job, great to see further updates.

2 Likes

Here is the contract which allows the user’s funds to be spent only for a specific bid or returning to her. Please let me know if anything is overlooked.

{
  val userAddress = PK("$userAddress")
  val bidAmount = $bidAmountL
  val endTime = $endTime
  val placeBid = {
    HEIGHT < endTime && INPUTS(INPUTS.size - 1).id == fromBase64("$auctionId") &&
      OUTPUTS(0).R8[Coll[Byte]].get == userAddress.propBytes && OUTPUTS(0).value == bidAmount
  }
  val returnFunds = {
    val total = INPUTS.fold(0L, {(x:Long, b:Box) => x + b.value}) - 4000000
    OUTPUTS(0).value >= total && OUTPUTS(0).propositionBytes == userAddress.propBytes
  }
  sigmaProp(placeBid || returnFunds)
}
4 Likes

The Ergo Auction House is integrated with the assember service and is in the testing phase.
It now supports any wallets for placing bids. I have created some test auctions in order to test both the new changes in the Auction House and the new assembler service before deploying it to ergoauctions.org to make sure there are no issues with the assembler service.

You can find the new version here. Please participate and spread the word to make sure all is ok for deploying.
Report any issues here or on Github.

Just use the “Assember” option when configuring the wallet and you are good to go!

4 Likes

Awesome work @anon_real, super cool to see this already coming to life after such a short span of time.

2 Likes

Thanks, @robert. I will be away for a few days and then I’ll write a detailed explanation of how the assembler service should be used for other dApp developers.

1 Like

The Ergo Auction House is updated! It is now possible to use any wallet in a trustless and secure manner to place bids thanks to the assembler service.
Also, the update contains some improvements for interacting with the explorer.

Enjoy the Auction House with your favorite wallet!

4 Likes

Now running on HTTPS! https://ergoauctions.org/#/auction/active

3 Likes

How To Issue An Artwork NFT Auction:

1 Like

Continuing the discussion from Some Details About Ergo Auction House:

Hi Anon- I was trying out the auction house for the first time today, actually won a bid for a small NFT. I entered a Yoroi wallet as it does say Yoroi supports tokens, however after winning the bid, i only see an incoming transaction to my yoroi wallet for 0.001 ERG. I’m sure I’m just not understanding but if someone can explain that would be helpful how I can confirm receipt of the NFT.

1 Like

Hi @gmakri01.
Your NFT is safely stored in the Yoroi wallet but the UI currently doesn’t show it which will be added soon reportedly. So as long as you keep a little bit of erg in your Yoroi wallet, your NFT is safe and will be shown when UI supports it.

Thanks so much for the quick response. Appreciate your help!

1 Like

Ergo Auction House now supports presenting the artwork!

As a part of the Artwork NFT standard, if the artwork’s URL is present in register R9 of the issuing box, then it will be detected and shown in the Auction House. To support that, ergoutils.org is updated to support uploading the artwork automatically without any further work needed by the user – this is optional and is helpful only for presenting the artwork.
The only thing that needs to be done is to enable “Upload Artwork” when issuing the NFT and the rest will be taken care of automatically.
However, this will be effective from now on and current active auctions can not be presented since they have not followed the above standard.

Some test auctions are available here: https://test.ergoauctions.org/#/auction/history

4 Likes

Hi Community!

I have received many requests for improving the UI/UX for Auction House. I have already addressed some of them but have been extremely busy with other stuff so couldn’t address some of them until now.

Since currently all of the auctions are Artwork auctions, I have updated the site to better fulfill the needs of artists.

First, the design for active auctions is completely changed:

Second, new filters have been added so that artist can follow the progress of their own artworks easier:

So currently, Auction House is friendlier to artists but not others (for example those who want to sell ordinary tokens – there are none currently) so the code needs a lot of refactoring to generalize it again for all use-cases which I will do when I get some rest!

Please note that Auction House, unfortunately, has no other contributors and I have plenty of other, mostly more critical, things to do in the ecosystem. I will provide donations for those who are willing to contribute to the project and address users’ notes for improvements.

Enjoy!

6 Likes

https://ergoauctions.org now supports audio NFTs - check it out here!

You can issue your audio NFT using https://ergoutils.org.

5 Likes

Please note that the link to audio has to be direct!
When you paste the link in the field in ergoutils, you should be able to listen to the audio in the player that shows up, otherwise, your link is not direct.

2 Likes

The auction house now supports artist page. Anyone can click on the artist address to see all his works.

Artists can share their page (all their artworks) on their socials. Example: Ergo Auction House

In general, if you for example have 3 addresses address1, address2, and address3 then your page will be: /#/auction/active?type=picture&artist=address1,address2,address3 - you can share your page to both present all your artworks and show authenticity of NFTs.

The artist of an artwork is determined by who has sent the necessary funds to issue the artwork. So I suggest to use a Yoroi wallet and use just a few addresses in that wallet for your artworks to be presentable easily,

7 Likes