Git Product home page Git Product logo

name-bazaar's Introduction

District0x Discord server LICENSE pull requests welcome Build Status

Name Bazaar

A peer-to-peer marketplace for the exchange of names registered via the Ethereum Name Service.

See at https://namebazaar.io

Smart-contracts can be found here.

Starting a dev server

In a terminal, start a ganache blockchain

./run-ganache.sh

Note that this uses docker and will try to pull trufflesuite/ganache-cli:v6.12.1 image if you don't have it.

Alternatively, you can connect directly to one of ethereum testnet networks - e.g. goerli. In order to do this, specify correct smart contract addresses and :web3 properties in the ./config.edn file. Example config file can be found in docker-builds/server/config.example.edn.

Open another terminal, start a repl and build the dev server (with figwheel repl)

lein repl
(start-server!)

Figwheel will prompt for a connection for the repl instance.

Open another terminal, run the compiled server script, which should connect to the figwheel repl.

node dev-server/name-bazaar.js

(If you have problems re-running this command, try removing dev-server folder and try to start the server again)

Redeploy smart-contracts and generate mock data

You can (re)deploy contracts with

truffle migrate --reset

and (optionally) generate some samle dev data from the clojurescript REPL by running the following command:

(generate-data)

Redeployment / generation can take a long time, please be patient.

Start dev UI

If you wish to connect to the dev server discussed above, open a separate terminal, and build the client-side ui

lein repl
(start-ui!)

You can then connect to the server through a web browser at http://localhost:4541

Semantic UI

To build the Semantic UI pieces of the app you need to have gulp installed. Note that gulp 4.x does not work, you need a 3.x version.

npm install gulp@^3.9.0 --save

Then use our handy script:

./semantic.sh build or ./semantic.sh watch

Depending upon how you'd like to work.

Start a development UI for client-side development only

If you're only focusing on working with the UI, you can start a UI interface which connects to the production server using mainnet.

lein repl
(start-ui! :ui-only? true)

In separate terminal, start the supplied docker nginx server

docker-compose build nginx
docker-compose up nginx

# Visit website at http://localhost:3001

Note: using this client is using the main ethereum network, it is ill-advised to carry out transactions unless you know what you are doing!

Backend (server) tests:

lein doo node "server-tests"

(If you have problems running the tests, try to remove server-tests directory and try re-running the tests again)

The doo runner will autobuild the test and re-run them as the watched files change. Alternatively:

lein cljsbuild once server-tests
node server-tests/server-tests.js

Frontend (browser) tests:

To run browser tests use the following command:

lein npm run cypress-open

Tests connect to a running app on http://localhost:4541. It is recommended to run the tests with clear ganache network, otherwise the tests will be slower or fail.

Development env through nginx:

docker-compose build nginx
docker-compose up nginx

and start (start-ui!), (start-server!) as usual, but open the site on http://localhost:3001

Build for production

Following commands are used to build system for production

lein build-prod-server
lein build-prod-ui
lein build-css

# To build all 3 in parallel use
lein build-prod

# To run prod server
node server/name-bazaar.js

Testnet deploy

To run server in docker container use image district0x/namebazaar-server, e.g.:

docker run --name=namebazaar-server \
    --net=host \
    -v /path/to/config.edn:/configs/namebazaar.config.edn \
    district0x/namebazaar-server:latest

You can choose between tags dev, latest (intended for QA deploys) and release (intended for production deploy). As for the config file, you can find an example in docker-builds/server/config.example.edn. Of particular interest is providing correct addresses of smart contracts on the blockchain you'll link the app to.

For UI use the district0x/namebazaar-ui image:

docker run --name=namebazaar-ui \
    --net=host \
    district0x/namebazaar-ui:latest

Note that there is no passing of config file for UI: currently for any change of UI config you need to build a new image (see the next section). The hardcoded configuration is at src/name_bazaar/ui/config.cljs.

Deploying Name Bazaar smart contracts

First, you need to specify deployments secrets in config.edn. For example:

{:truffle {:goerli {:privateKeys ["0x0000..."]
                    :infuraKey "0000...."
                    :ensAddress "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
                    :registrarAddress "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85"
                    :publicResolverAddress "0xE264d5bb84bA3b8061ADC38D3D76e6674aB91852"
                    :reverseRegistrarAddress "0xD5610A08E370051a01fdfe4bB3ddf5270af1aA48"}}}

ENS address are not in documentation, but in some random post on forum https://discuss.ens.domains/t/deployment-of-new-contracts-inc-namewrapper-to-testnet-goerli/14505

Then, you can use truffle to deploy the contracts just by running the following command in bash:

# you can also use `--network mainnet` - see truffle-config.js for deployment details for more information.
truffle migrate --network goerli

Linting and formatting smart contracts

We use ethlint for linting solidity files. You can use lein npm run ethlint and lein npm run ethlint-fix to run the linter.

You can use lein run-slither to run slither to statically analyze the smart contracts. However, this tool reports many false positives.

name-bazaar's People

Contributors

danielglauser avatar fbielejec avatar floorlamp avatar kwladyka avatar ladislavdubravsky avatar madvas avatar siegrift avatar sm47916 avatar wambat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

name-bazaar's Issues

Manage Names Page

New Manage Name Page should look like this:

image

Point Name to an Address

  • Address input stays disabled when user has no resolver set up
  • Address input is pre-filled with :active-address, but allows different address for input
  • Address input checks for validity with web3/address?
  • If invalid input or user is not owner of the name, submit button is disabled
  • When user has resolver set up, "Before you..." text is not displayed and submit button text is "Set Address"
  • Transaction log text is: "Point address to [name]"
  • Setup Resolver transaction log text: "Setup resolver for [name]"
  • Setup resolver sets default public resolver address 0x5ffc014343cd971b7eb70732021e26c35b744cc4

Point Address to a Name

  • Input is validated with valid-ens-name?
  • User does not need to be owner of the name
  • Pointing address is :active-address
  • When user has resolver set up, "Before you..." text is not displayed and submit button text is "Set Name"
  • Transaction log text is: "Point [name] to my address"
  • Setup Resolver transaction log text: "Setup resolver for my address"
  • Setup resolver sets default public resolver address 0x5ffc014343cd971b7eb70732021e26c35b744cc4

Create Subname

  • Input is validated with valid-ens-name?
  • Doesn't need to check if such subname is already created. Simply overwrites
  • If user is not owner or invalid or empty input, submit button is disabled
  • Transaction log text is: "Create [name]"

Transfer ownership

  • Input is validated with web3/address?
  • If user is not owner or invalid or empty input, submit button is disabled
  • Text in the picture is displayed only for top level domains. For subdomains display following text: "Address [new-owner] will become owner of [name]"
  • Transaction log text is: "Transfer [name] ownership"

Add to Toshi

Make NB work in toshi. From what I read, you need to create chat bot and then give it WebView action. WebView should have injected web3 automatically, so everything "should" just work.
Please create repo for chat bot under district0x organisation as name-bazaar-toshi.

Chatbot should work basically the same way as Cryptokitties one. It should display one menu with links and one button to visit page.

UI should be already mobile friendly, but Transaction Log opener is currently hidden for mobile screens. You'll need to enable it following way: (only CSS)

Current state:

image

Desired state:

image

Social Share buttons

Add sharing functionality into Facebook and Twitter buttons on My Offerings and offering detail pages. Beware, when user wants to share My Offerings page, it actually should share his user offerings page: /user/<useraddress>/offerings., not /my-offerings

Don’t include invalid names in search & disable buying

Problem

Users can create offerings outside namebazaar UI and therefore go around UTS46 normalisation and create offering for what we would consider invalid name.

Solution

Into name-bazaar.shared.utils/parse-offering add 2 more props:

  • :offering/valid-name?, which has result of name-bazaar.ui.utils/valid-ens-name?
  • :offering/normalized?, which is true if name stays exactly same as when run through normalize function. In browser it's js/EthEnsNamehash.normalize in node.js (aget (js/require "eth-ens-namehash") "normalize"). (Must detect environment to choose correct one)

In db_sync.cljs on on-offering-added event, we simply skip adding into in-memory db offerings that have either :offering/valid-name? false or :offering/normalized? false.

That way we get it out of search results, but such offering will be still accessible on offering detail page in UI.

In UI we add warning, same way as below and disable buy/bid button in both cases.

image

Warning text for both cases:
WARNING: Offered name is not compatible with UTS46 normalisation, therefore buying or bidding is disabled.

Email notifications

Goal

Users should get email notification when:

  • Offering was created for name requested by user
  • Seller's Buy Now offering was bought
  • Seller's Auction offering got new bid
  • Auction was finalized. Both seller and buyer receive email

Steps of implementation

  1. Research on libraries to use for encrypting/decrypting user's email on blockchain. (Public/Priv key encryption)
  2. Implement encryption on client side via public key. Saving email is already implemented, just encryption logic is missing.
  3. Implement decryption on server side via private key. Private key should be pulled from ENV.
  4. Fix OfferingRequests. At the moment OfferingRequests contract wipes out all requests as soon as offering for particular name is created. This is not correct, because we need to be able to access requester's addresses so we can send them email notification. Possible implementation might be like: requests are never wiped out, rather index is incremented in multidimensional array, when offering is created. Data structure might look like this:
struct Requests {
        string name;
        uint latestIndex; // Increments every time new offering is created
        mapping(uint => address[]) requesters;
        mapping(uint => mapping(address => bool)) hasRequested;
    }
  1. Implement emailer app, that listens to blockchain events and sends out emails via SendGrid. For inspiration check out ethlance-emailer where this was already implemented. Not sure if we do this as separately compiled app or as a part of running server. Opinions welcome.

Move setting up URL listeners into reg-fx

Those side effects should be done in reg-fx and called as regular re-frame events.

(if history/hashroutes?
(set! (.-onhashchange js/window)
#(dispatch [:district0x/set-active-page (d0x-ui-utils/match-current-location constants/routes)]))
(history/start! constants/routes))

But why?

The problem is that (history/start! constants/routes) fires [:active-page-changed] even before app is bootstrap, therefore before :district0x/smart-contracts-loaded. This causes error, because :active-page-changed assumes :district0x/smart-contracts-loaded.
Currently I used little hack to avoid error:

(when (all-contracts-loaded? db) ;; Pushstate URLs fire first event too early
(route->initial-effects (:active-page db) db))

So make it an re-frame event that's fired here at bootstrap
:dispatch-n [[:district0x/watch-my-eth-balances]

For (.-onhashchange js/window) we already have district0x.ui.window-fx file, you can put new reg-fx there.
For (history/start! constants/routes) you can create district0x.ui.history-fx. Don't put into district0x.ui.history because this file is required many times, so reg-fx is not overwritten every time.

Prefill Create Offering name from URL query param

URL like https://namebazaar.io/offerings/create?name=bitcoin should prefill name input for creating offering and trigger ownership check.

On ENS name detail. e.g https://namebazaar.io/name/buterinvitalik.eth, or when expanded offering request: If :active-address is :ens.record/owner there should be new link displayed below "Open in Etherscan" and "Add to watched names" -> "Create offering", that will go to create offering page and prefill name input.

This feature will come in handy for prepared Registration feature, so this should be ready before implementing Registration.

HTML5 pushstate urls

Right now we're using urls like: https://namebazaar.io/#/offerings, we need to change that into urls like https://namebazaar.io/offerings using pushy library. This is needed as a preparation for Open Graph implementation, which will be done later. Since things behind # are not sent to server.

This task also includes modifying server config so for any path server returns root path index.html. Otherwise ipfs won't find a file.

Also, if detected using other domain than namebazaar.io (or localhost), front-end should fallback into # urls again. Because if site will be accessed via ipfs like for example: https://ipfs.io/ipfs/QmVe5ebTzNjDcpL6ycRga2Vyk66cVZksTzkxMaHo9z6795/offerings, it won't find a file. Must be https://ipfs.io/ipfs/QmVe5ebTzNjDcpL6ycRga2Vyk66cVZksTzkxMaHo9z6795/#/offerings

Improve HashRegistrarSimplified.sol

This is preparation issue for name registration issue.

Currently we have at ens/HashRegistrarSimplified.sol modified version of original HashRegistrarSimplified.sol. Modified in a way that it supports instant registration for development purposes of our project. The problem is, I modified it in too impactful way, that it no longer can serve as original registrar, only instant registrar.

Your task is to take again original registrar code and add function register for instant registration, but don't modify other functions of contract, so it still can be used in original way, which we'll need for development of name registration.

Function state doesn't need to return correct state for instantly registered names, because that would complicate things too much.

Here's example of current register code:

function register(bytes32 _hash) {
        startAuction(_hash);
        var sealedBid = shaBid(_hash, msg.sender, msg.value, 0);
        newBid(sealedBid);
        unsealBid(_hash, msg.value, 0);
        finalizeAuction(_hash);
    }

The problem is that function calls all these high level functions, which have modified internals of them. What you need is to put internals into register function (without unwanted conditions) and high level functions like startAuction, newBid, etc. leave untouched.

Used names

Hello,

What are some names that are actually used?

Where else can these names be bought?

Migration to CSS Grid

Explore possibility to move from Semantic Grid into CSS Grid. If this proves to be feasible on NB, we'll use that for all other districts. The end goal is to separate components code from visual layouting as much as possible. That means, moving layouting into CSS.

I'm not sure how smooth can migration be, but would be great if it can be applied continuously without breaking current layout. So, if you migrate some components, commit it, we'll take a look and test in different browsers and if all good, you'll continue. NameBazaar should look exactly same after migration.

There seems to be multiple ways of doing CSS Grid, like via grid-template-areas or grid-template-rows, etc. I don't know I'm no expert, so play around it and find best way ;)

Edit: We'll still keep other Semantic components unrelated to layouting as they are

Enable winning bidder to bid again

Currently it's disabled for winning bidder to bid again. This might be needed if user wants to raise bid and leave away from computer.

For this issue, make changes only in smart contract: AuctionOfferingLibrary.sol. And also add some simple test for this: When user overbids himself, highest bid is correctly added up and user has no pending returns.

You don't need to make changes in UI for this issue.

Order by finalized date for Sold offerings

When viewing "Sold" offerings 2 extra options should be added into Order By select bar:

  • Newest finalization
  • Oldest finalization
    When clicking on "Sold" link, "Newest finalization" should be chosen by default, therefore name-bazaar.ui.utils/offerings-sold-url should contain these params.

Select field already has those 2 options, just rename them to:

  • Newest finalization
  • Oldest finalization

:offering.order-by/finalized-newest "Newest"
:offering.order-by/finalized-oldest "Oldest"

User-friendly urls for user pages using ENS

Right now we have pages like:
https://namebazaar.io/user/0x24ac2648175b1b9a3564ad6a3680569dfbb896b7/offerings
https://namebazaar.io/user/0x24ac2648175b1b9a3564ad6a3680569dfbb896b7/bids
https://namebazaar.io/user/0x24ac2648175b1b9a3564ad6a3680569dfbb896b7/purchases

Goal is to be able to use URLs like:
https://namebazaar.io/user/johndoe/offerings
https://namebazaar.io/user/johndoe/bids
https://namebazaar.io/user/johndoe/purchases

Where johndoe would represent address resolved from ENS name johndoe.eth.

So when application detects that in URL is not an address (cljs-web3.core/address? is false), it'll try to perform ENS lookup.

Steps you'll need to to do to be able to do lookup:

  1. add ens/PublicResolver.sol contract to compile-solidity.sh
  2. add :public-resolver entry with zero address into name-bazaar.shared.smart-contracts, so UI loads ABI at app start up.
  3. When name in URL is detected it first loads resolver address (use :ens.records/load).
  4. If resolver is not set, it displays "No user associated an address with this name." instead of list of names.
  5. If resolver exists it uses PublicResolver.sol method addr to try to load associated Ethereum address. If it's valid non-zero address, then continues loading page as normal. If it's not valid address it displays same error as in step 4.

Force Character Count To Be 7

I think this needs to be fixed, because right now people think you can have ENS names like one.eth, dog.eth, wall.eth... I think this needs to be addressed at least in requested names. Here's pictures for references:
https://i.imgur.com/15DjRDN.png (namebazaar request page)
https://i.imgur.com/kVh0ZLp.png (only domains with 7+ char count can be created)

I suggest that words with less than 7 characters shouldn't be seeable.
https://i.imgur.com/np9Igw3.png (In this case clicking enter should pop an error message saying the char count is less than 7)

If I remember correctly, the char count limitation will be decreased to 4 chars in the future, but there's still a lot time before that. Therefore, NameBazaar is misleading in this sense, so I feel this should be addressed in the following commits and fixed.

Add Trezor Support

I just realized I hold all my ENS domains on my trezor wallets. Trezor users can't use metamask and even if we could export our keys, we would rather not. Namebazaar needs to be supporting hardware wallets too.
I guess explicitly supporting Trezor isn't necessary as far as you provide us with the contract addresses and ABI's to interact with contracts without the website.

Add Ledger Nano S Support

It would be great to be able to sign in using the Ledger Nano S as I can't connect addresses to Meta Mask etc.

Suggestion form audit: Unnecessary complication due to transferPrice parameter to AuctionOffering.finalize

Implement changes related to following point from audit: https://gist.github.com/Arachnid/3416e5a85b5b67eb9cdfa2252a5e28d9#unnecessary-complication-due-to-transferprice-parameter-to-auctionofferingfinalize

We can remove transferPrice parameter and instead make fallback automatic. To do so, we'll use Solidity's send function instead of transfer.
send function doesn't throw error if transacting fails, but returns false.
So instead of this

if (transferPrice) {
    offering.originalOwner.transfer(offering.price);
} else {
    self.pendingReturns[offering.originalOwner] =
    self.pendingReturns[offering.originalOwner].add(offering.price);

We'll write this:

if (!offering.originalOwner.send(offering.price)) {
    self.pendingReturns[offering.originalOwner] =
    self.pendingReturns[offering.originalOwner].add(offering.price);    
}

In similar fashion we can edit bid function, where funds will be tried to sent to overbid user instantly and only after that fails, we'll put it into pending returns. Tests will need to be edited, that instead of pending returns it checks user's balance if overbid amount was returned.
Testing fallback pending returns scenario would be pretty tricky, it would require creating contract with fallback function that always fails and bid through this contract. I'd leave implementations of this after release, as we have more important tasks to do first.

Register Name Page

Implement page for ENS name registration.

These 2 issues must be done, before this issue: #102 and #92

Here are designed screens with different states of registration:

State: Name is available

As user types into text field, app checks state of the name. (:registrar.entries/load)
When name is available we display screen as below on the screen.
Put Lorem Ipsum meanwhile there, there will go some instructions
"Bid Now" button calls startAuctionsAndBid of Registrar
"Open Without Bids" calls startAuction

nb1

State: User made bid

For "Add to Calendar" use react-add-to-calendar
Button is disabled until reveal phase happens
Disabled button doesn't need to look like on designs, just pass it :disabled true

nb2

State: Auction is open, but user hasn't made bid

I don't have screen for this state, but it's basically same as previous screen, with text under input from first screen ("The name is available for bids") and form is also like first screen except "Open without bid" button is not there.

State: Bid is waiting to be revealed

If there's no highest bidder yet, write "none".
Winning bidder link should go to user offerings page
nb3

State: User is winning the auction

Basically same as previous screen. "Finalize" button is disabled until end of reveal phase.
nb4

State: User has been outbid

nb5

State: User is owner of the name

Create offering button goes to create offering page with pre-filled offering name
For Name Information and Registrar Information reuse component we already have from name detail page. Design does not reflect exactly what we have currently in app, ignore that.
Time to renewal is 2 years from the end of the auction.

nb6

State: Name is owned, but not by current user

nb7

Import Bids/Backup Bids/Remove Name

As you can see, on each screen there are 2/3 of these buttons. When user makes bid, he must seal it, so others can't see how much he has bid. You seal bid in following way: sha3(ENS node, User Address, Value of Bid, Salt). Where Salt is hashed password user should choose. See Registrar smart-contract for more details, or Google. We'll generate Salt string for users, from random 10 char string (district0x.shared.utils/rand-str). Then we'll be storing those hashed salts in localstorage, so users can later reveal bids. For hashing Salt use name-bazaar.ui.utils/sha3
So:
When user sends bid transaction or just opens auction, we save bid into :registration-bids in db (which will be synced with localstorage).
When user clicks "Backup bids", it exports contents of :registration-bids as JSON and exports it to browser. Similarly as https://registrar.ens.domains/ does it.
"Import Bids" will do other way around. Read JSON file and import bids to :registration-bids and localstorage. If imported file is invalid, snackbar informs user.
At certain states, "Remove name" is available. It is to remove current name from :registration-bids. This button is displayed only if user actually has current name in :registration-bids.
Format of :registration-bids as well as exported JSON file is:

{user-address {node {:name "somename.eth" :salt "0x12345..."}}}

User opens registration page

So, when user opens registration page, app loads current state of all his :registration-bids for current :active-address. (:registrar.entries/load)
Make sure you don't just load phase from Registrar smart-contract, but calculate it client-side and compare to :now, as we want to have phase changed in UI automatically while user is on the page.
Under the text field it always shows the most important information about his :registration-bids state. These are all possible texts there, ordered by importance (It always shows only 1 line at the time, the most important one):

  • %s bids are waiting to be revealed (user has made bid(s), now it's reveal phase, needs to reveal)
  • %s bids are waiting for finalization (user has won, reveal phase is over, now needs to finalize)
  • %s names are waiting for a bid (user opened auction, but haven't made bid, reveal phase has not started yet)
  • %s bids are winning (user's bids are winning, waiting for end of reveal phase)

nb9

User click on text field

When user clicks on text field, it gives him autocomplete suggestions of :registration-bids for current :active-address.
Each row also displays current state of a bid. This are all possible states, in order they should be displayed in suggested list (by importance):

  • Waiting to be revealed (user has made bid, now it's reveal phase, needs to reveal)
  • Waiting for finalization (user has won, reveal phase is over, now needs to finalize)
  • Waiting for bid (user opened auction, but haven't made bid, reveal phase has not started yet)
  • Winning (user is winning, waiting for end of reveal phase)
  • Outbid (the other user is winning and haven't finalized yet)
  • Waiting for reveal phase (user has made bid, reveal phase hasn't started yet)
  • Finalized (user won and finalized, now owns the name)
  • Owned (other user won and finalized)
  • Loading (placeholder while we haven't loaded bid state yet)

nb8

Development

To be able to effectively test all different states, you'll need to be fast-forwarding time in TestRPC (cljs-web3.evm/increase-time!) as well as fast-forwarding :now in re-frame db. Or you can modify phase durations in HashRegistrarSimplified.sol. You can try both approaches.

I already added all icons you'll need, here are classes:
.arrow-up Winning during reveal phase
.hammer-remove Remove Name
.hammer-arrow-left Import Bids
.hammer-arrow-right-left Backup Bids
.flag2 Waiting for finalization
.dots Waiting for reveal phase
.hammer2 User made bid, waiting for reveal phase
.loading Loading
.user2 Name is owned
.check Finalized
.clock2 Bid is waiting to be revealed
.times Outbid

Please commit continuously so I can review
Happy hacking!

Error when server is not synced yet

When server is not synced yet, but requests are coming to server it spits following error:

{:level :error, :message "Unexpected error occured", :meta {:raw-error #object[TypeError TypeError: Cannot read property 'get' of null], :error {}, :ns "name-bazaar.server.api", :line 23, :file "/home/ubuntu/name-bazaar/src/name_bazaar/server/api.cljs"}, :?file "/tmp/form-init1063880031196546695.clj", :?line nil, :timestamp #inst "2017-10-30T01:43:49.871-00:00"}

https://logs.district0x.io/_plugin/kibana/app/kibana#/doc/filebeat-*/filebeat-2017.10.30/doc?id=AV9q8wlmVoPdgHj4OByJ&_g=()

It should return 503 Service Unavailable error.
Have suspicion that this somehow interferes with syncing itself, but not confirmed.

Internal smart-contract audit + adding 1 test scenario

In commit 59bd456 were addressed all outstanding issues from audit.

Could you please perform small audit on contracts before we send it back to Nick for final look. Also please add 1 new test scenario I'll describe below.

Issues that were addressed:

Dispatcher pattern is obsoleted by Byzantium

Now we use very thin proxy contract Forwarder, which proxies all functions to deployed instance of BuyNowOffering.sol or AuctionOffering.sol, which are singletons used only for logic, not storing data. You can read more about this pattern here

Use of require instead of modifiers

Since we don't use Solidity's libraries, we can use modifiers in offering contract.

Use of 'address' instead of strongly-typed alternatives

This has been changed throughout the app

Storage of duplicate data

This was solved by putting placeholders into offering contracts, which will be replaced after compilation. This way those addresses don't have to be set on contract initialisation run by user, therefore user doesn't have to pay gas for it.

Bid value is implicit

This was solved by removing reusing pending returns for new bids

Hardcoding of ENS registrar address

Instead of passing registrar contract address, now we access it's address by ens.owner(namehash("eth")), which should stay up to date even if registrar address changes in the future.

Winning bidder can claim both name and funds with emergency multisig assistance

This was solved by adding onlyWithoutNewOwner into reclaimOwnership function.

Emergency intervention requires time-critical operations on every open offering

Offering registry has now variable isEmergencyPaused, which can disable buy/bid/finalize function on all offerings at once. Please write test scenario when isEmergencyPaused is used.

Get Email template up and running

Here are files for email template: Email Template.zip.

Ask me for Sendgrid credentials on chat. You should create a template there. You'll see Ethlance template there already. See how substitutions are done there. Substitutions are placeholders that get replaced programatically when sending email. In ethlance-emailer it's done like this. So you should have 4 substitutions here: Header title, Body text, Button text, Button href.

image

Smart-contract tests

Tests must be extra comprehensive as contracts deal with money and name ownerships.

Tests should be added here: https://github.com/district0x/name-bazaar/blob/master/test/name_bazaar/smart_contract_tests.cljs

Following things should be tested: (if you think I forgot sth, feel free to add).
You can reorder testings of those things as it makes most sense codewise.

  1. Contracts setup after deployment
  • Check if all properties of contracts are setup correctly after deployment. Especially addresses of interconnected contracts.
  1. Create buy now/auction offering.
  • for TLD (e.g abc.eth), user can create offering only when is owner of both, ENS name and deed.
  • throws error when user creates offering for TLD and is owner of ENS but not owner of corresponding deed.
  • for subname (e.g fge.abc.eth) user can create offering only when is owner of ENS name.
  • throws error when user created offering for subname, but is not owner of ENS name
  • created offering has the same properties as passed into creation method.
  • auction can't be created with earlier end date as now
  • auction minBidIncrease can't be 0
  1. Buying Buy Now offering:
  • Buys successfully when sent ETH equals to offering price.
  • throws error when sent ETH is not equal to offering price.
  • throws error when trying to buy, but offering is not the owner of ENS name (for TLD also deed owner)
  • After buying new owner is the owner of ENS name (for TLD also deed owner)
  • After buying newOwner is correctly set in the offering contract
  1. Bidding Auction Offering
  • Bids successfully if sent ETH equals or is greater than auction start price. Checks if all relevant properties in contract were updated.
  • throws error if otherwise above
  • Bids successfully if sent ETH equals or is greater than currently highest bid + minBidIncrease
  • throws error if otherwise above
  • if user has bid before, it's enough for him to send only difference needed for next bid.
  • throws error when trying to bid, but offering is not the owner of ENS name (for TLD also deed owner)
  • Bidding can correctly extend auction endTime according to extensionDuration
  1. Withdrawing pending returns from auction offering
  • User who was overbid, can successfully withdraw funds from auction offering.
  • user can't withdraw twice.
  • Emergency address can withdraw funds to a user's address on his behalf.
  • Pending returns can be still withdrawn even after auction successfully ended and name was transferred to a new owner.
  1. Finalizing auction
  • Can be finalized only after endTime
  • Can't be finalized if no one has bid
  • Can be finalized with parameter transferPrice = true, therefore transfers ETH funds to original owner
  • Can be finalized with parameter transferPrice = false, therefore puts ETH funds into pending returns for original owner.
  • After finalization transfers ENS name ownership correctly (for TLD also deed ownership) and sets offering properties accordingly (newOwner)
  1. Reclaiming ownership:
  • For Buy Now offering, original owner can reclaim ENS name ownership (for TLD also deed ownership)
  • For Auction offering, original owner can reclaim ENS name ownership (for TLD also deed ownership) only when there are still 0 bids, throws error if otherwise
  • Emergency address can reclaim ownership on user's behalf.
  • For auction, emergency address can reclaim ownership also for auctions with bids, puts winning bid into pending returns for bidder.
  1. Offering Editing:
  • Offering can be successfully edited by original owner, throws error if different address tries to edit.
  • Auction offering can be edited only when has 0 bids, throws error if otherwise.
  1. Changing register address
  • Emergency address can change register address property of offering contract. Throws error for other address.
  1. Requesting ENS names
  • user can successfully request ENS name and it increase counter of requests.
  • if offering is created after that, it zeroes requests counter

Server side logging

Implement comprehensive logging of all actions happening on node.js server.

Events types that should be logged:

  • All Sent emails
  • All events listened to in db_sync.cljs
  • All HTTP requests on API
  • Any errors happening during events above

Server blockchain syncing connection recovery

db_sync.cljs should be able to recover if underlying blockchain node is restarted/disconnected and got online again.

All listeners should be stopped once we get first connection error, so we don't get flooded with additional errors. Then there should be interval checking every second if we got online again and setup syncing listeners again.

In-memory db should be wiped out and start syncing all over again, because we don't know what data was added meanwhile Ethereum node was offline.

Delete offer ?

I have one domain listed for both auction and buynow, how do I delete one ?
Actually one of them has ownership issues as the transfer was done via the other one. Is this why the domain is not listed in the search area ?

Removing offering feature

Adding "Delete" button for offerers to remove offering.

Steps to implement:

  1. Add following code into Offering.sol
    /**
     * @dev Modifier to make a function callable only when offering contract doesn't have name ownership
     */
    modifier onlyWhenContractIsNotNodeOwner() {
        require(!isContractNodeOwner());
        _;
    }
    /**
    * @dev Unregisters offering for not displaying it in UI
    * Cannot be run if contract has ownership or it was already transferred to new owner
    */
    function unregister()
        public
        onlyOriginalOwner
        onlyWithoutNewOwner
        onlyWhenContractIsNotNodeOwner
    {
        // New owner is not really this address, but it's the way to recogize if offering
        // was unregistered without having separate var for it, which is costly
        offering.newOwner = 0xdeaddead;
        fireOnChanged("unregister");
    }
  1. You'll need to bump version of contract here:
    var version = 1; // versioning for BuyNow offerings starts at number 1
    to number 2
    var version = 100000; // versioning for Auction offerings starts at number 100000
    to number 100001
  2. You'll add logic to name-bazaar.server.db/search-offerings to not return offerings with :new-owner of 0xdeaddead, similarly as there's handling of emergency-state-new-owner.
  3. In UI add "Delete" button, which is displayed under same conditions as "Transfer Ownership" button.
  4. After deletion is processed and offering is still open, there should be displayed red text about offering being deleted. Similarly as there's warning about emergency cancel.

    I suggest you to add prop :offering/unregistered? into name-bazaar.shared.utils/parse-offering and do detection there.

This is all very straightforward, but life ain't that nice and easy. We need to support deletion for already existing offerings. I recommend following hack:
When you detect offering version is 1 or 100000 (can add prop :offering/supports-unregister?),
use methods :buy-now-offering/set-settings and :auction-offering/set-settings to set some very unlikely price. e.g 23423982302342 (in wei) and that way you'll simulate deletion. Rest is pretty much the same pattern. On surface user should not be able to tell difference.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.