Coder Social home page Coder Social logo

universitydao / udao Goto Github PK

View Code? Open in Web Editor NEW
4.0 0.0 4.0 2.53 MB

The official UniversityDAO DApp repository.

License: GNU Lesser General Public License v2.1

Solidity 4.12% JavaScript 92.59% HTML 0.43% CSS 1.89% Python 0.97%
blockchain hardhat javascript solidity vite react polygon

udao's Introduction

UniversityDAO Website and App

Our website for the UniversityDAO organization. It contains full functionality for submitting proposals and voting on them.

Requires git and Node.js to build and run.

Testing Environment

  • OS: Any
  • Kernal: Any

Dependencies

  • git
  • Node.js

Build and Run

git clone https://github.com/UniversityDAO/udao.git
cd udao
npm install
npx hardhat compile
npm run dev

Contributing

Pull requests

  • Pull requests should always be reviewed by at least one other UDAO member prior to being merged.
    • Exceptions include very small pull requests that are not critical to functionality (ie. making frontend buttons look nice)
  • Mark unfinished pull requests with the "Work in Progress" label.
  • When you start work on something you should have a pull request opened that same day. Or at least as soon as possible so others can be aware of the changes you are making.
  • You as the person opening the pull request should assign a reviewer.

Commit Hygiene

No stringent commit requirements, but in general:

  • Try to give clear commit messages.
  • When pulling from upstream, avoid git merge (and git pull). Instead, use git rebase in order to avoid merge commits, thus creating a cleaner history.

Merging

Once your pull request has been Approved it may be merged at your discretion. In most cases responsibility for merging is left to the person who opened the pull request, however for simple pull requests it is fine for anyone to merge.

If substantive changes are made after the pull request has been marked Approved you should ask for an additional round of review.

  • Use squash and merge if all commits in the PR can be summarized succinctly by a single message.
  • Use rebase and merge if each commit in the PR has its own significance.
  • Avoid just merge as it will create an extraneous merge commit.

License

GNU Lesser General Public License v2.1

udao's People

Contributors

austin-davis1 avatar cartercameron1 avatar jagger-harris avatar oslfmt avatar

Stargazers

 avatar  avatar  avatar  avatar

udao's Issues

Enhancing the proposal submission redirection

Right now the proposal submission redirection takes the user to a page that just says "Submitting proposal" or something along those lines. It would a nice enhancement to have a 2-step process to display to the user. Step 1 is we upload the proposal to IPFS and display "Uploading to IPFS" and Step 2 have something like "IPFS Upload now complete. Submitting to the blockchain. Please confirm proposal in Metamask".

ERC721

create an ER721 contract to keep track of voting members.

Naming schemes for ERC721 vs ERC20

I noticed some small discrepancies in the naming scheme between the ERC721 and ERC20 contracts and deployment scripts. We can discuss the proper names at our next meeting.

Nonmember can still "cast" a vote

While writing the tests for Governance.sol, I came upon something unexpected. I expected that when a non-member casts a vote, the function would throw an error, saying that this person is not a member. But it does not, and the reason is because the way the OZ contracts are designed, is that there is no concept of membership, technically. Rather it's voting power that allows someone to vote, and voting power is obtained by owning ERC20/ERC721 tokens.

When a non-member votes, the transaction will still complete successfully, but the vote will have no weight. This is because non-members have no NFT, and thus no voting power, and so their weight == 0. The vote is "cast", but it does not count for anything. As far as I can tell, the design is still safe for our purposes.

However, we'll probably want to have some function to check if a person is logged-in/a member on the frontend, and if not, don't even give them the option to vote, or have some message specifying why they can't. Otherwise, they could still "vote" successfully, but it just doesn't make too much sense from a UX pov @CptAstro @jagger-harris

Delegate Voting Power

When testing out the delegate function in the EthersTesting.js file, I noticed that calling delegate() 5 times on a single address gave it 5 voting power for all the proposals. Since the contracts themselves don't seem to prevent infinite delegation, we'll need some way to ensure (with the delegate button) that a user can't just infinitely delegate votes for themselves.

Implement landing page and dashboard

Complete a really simple landing page. Probably just title, and button to launch app. We need to figure out how this will work (I think the landing page is on web2 and launching dao button will open up the DAO on IPFS, but not sure).

Implement the dashboard. The main thing is the left-column navbar and the Connect Wallet button popup. Also implement some components on the dashboard, but not in detail as this is still subject to change.

  • Landing page
  • Dashboard

Connect Front-End to Back-End using ethers library

  • Javascript -> Solidity. Figure out how to forward data from frontend to Solidity. This includes CID from IPFS, possibly a MetaMask wallet address, and more as needed. When somebody submits a proposal/grant or votes, we need to invoke Solidity function calls that run their logic.
  • Solidity -> Javascript. Figure out how to retrieve CID, yesVotes, noVotes, and active status from Solidity. This data is needed to populate all the fields present on our site.

Learn and get react-router set-up

Get react-router setup for the frontend.

React-router is necessary to link and move between pages on our single-page app. Likely we'll have routes something like:
/home
/dashboard
/dashboard/proposals/active
/dashboard/proposals/inactive
/dashboard/grants/...
etc.

Then on each route the components will be rendered.

Confusing redirect after clicking on card and then clicking cancel

Right now if you click on a proposal card, and then click "cancel", it will redirect back to the proposals page, even when you clicked on the card in dashboard. It should go back to dashboard if you click the card on dashboard, and back to proposals page if you click on it in proposals page. Likely need to use browser history here, just to back, not a hard redirect in "cancel" button.

Reading financial data off the blockchain vs reading it off IPFS

We should be careful when displaying financial information on the front-end. what is submitted to IPFS does not have to matches what is on the blockchain. Theoretically, a malicious actor could create an IPFS file, manually pass it into the propose function and have a mismatch between what the function says it is going to do on IPFS, and what it is actually going to do on the blockchain. If our front-end only uses the blockchain to read the cid, and displays everything using IPFS, somebody could claim they are requesting x dollars, but in the transaction data on the blockchain request a different amount. We talked about malicious mismatched info at our last meeting @CptAstro but wanted to formally bring it up, and hear your thoughts on it.

Refresh Issue

Right now, as of the reading dataflow rework, we only load all the data onto the page ONCE and that's as soon as a user presses "Launch App" on the landing page. Once they do so, it directs them to a "Loading" page where we then fetch all the data. Once the data is fetched and done loading, we automatically redirect to the dashboard page.

The problem with this is what if we're on the dashboard/grants/proposals pages, and the user refreshes the page, the page ends up being empty. It's empty because once the page refreshes the entire app has to re-render, and once it re-renders the user will be left on whatever page they refreshed on, meaning they essentially 'bypassed' the launch app button. This is a bit of an issue.

One solution would be to have an event listener for page refresh, and upon refresh we redirect them to the loading page. where data will be loaded up. The issue with this solution is that if somebody is on the grants page and refreshes, once the data loads back in they're going to be on the dashboard page. Not an app-breaking problem but still annoying from a user standpoint.

IPFS and Ethers connection organization issue

With our current setup, we plan to call the propose() function using Ethers and passing in the IPFS CID as part of the hash. This forces us to upload to IPFS before we call propose(), as an IPFS CID is generated upon upload. This creates two problems:

  1. If we upload a file to IPFS then the propose() function fails, we have IPFS data sitting around that has no corresponding blockchain data. There is no easy way to delete this data, so it will just be stuck there when it shouldn't be there at all.
  2. We have to store Proposal ID's (the return value of propose()) anyways, so by uploading to IPFS before calling propose() we would be forced to create a new file to store every Proposal ID since we cannot append it to an existing proposal. This means every proposal or grant has two files for each entry, and this would drastically increase overall complexity and overhead on the frontend side.

Implement NFT smart contract

ERC-721 implementation. Can probably grab from OpenZeppelin. Look into how to use NFTs as login mechanism.

  • Implement NFT
  • Look into NFTs as login mechanism

Fix metamask sign-in workflow

Pretty buggy right now. Needs to be fixed all around. Maybe add a "logged in" state too, detecting membership NFT.

Implement proposals-related pages

Pages related to proposals. NOTE: since proposals pages are almost mirrors of grants pages, figure out to use components to the best of our advantage so we can just duplicate the logic.

  • Active proposals
  • Inactive proposals
  • My proposals
  • Proposal Form

How to set contract abis, address, and provider

Any idea if this is an expensive operation? It's called in every single single function. In fact, the lines of code from 38-40 are the same in each function, grabbing the address, abi, and provider. I'm wondering if there's a more efficient way to do this. Maybe set these in the root, like in App.js.

Originally posted by @victor-wei126 in #41 (comment)

Disable transfers of MembershipNFTs & revoke NFT for ex-members

Since these have no monetary value and are to represent membership and function as a login token, I think members shouldn't be able to "transfer" these NFTs. I can't think of any instance where someone would for any good reason, except to perhaps gain voting power. We would probably want to disable that, since we expect everyone to have a voting power of 1.

Some related issues are: how should we revoke these NFTs after someone is no longer a member, either because they graduated or left the DAO?

A possible solution is setting some sort of timestamp, after which the NFT is automatically transferred to the 0x0 address. I'm not sure if this is possible though. Opening this thread for discussion.

Labels on cards

Right now the labels on cards are just filler data not actually being pulled from each proposal.

Timer display

How are we going to display the time left until a proposal ends. The easiest way I see to is a block clock. We will display the ending block on the proposal, and have a counter displaying the current block somewhere near. The alternative would estimating block times and converting.

Block Clock

Pros:
-Easy to implement
-more precise
-no need to convert time zones

Cons:
-harder to know the end date
-not as visually appalling

I suggest we start with a block clock. At a later period in time, if we decide to switch methods we can implement and alternative solution.

What does everybody think about a block clock.

Error Handling in app

Error handling is practically non-existent right now. We'll need someone to devise an error checking plan and then test for errors and then solve them aka "bug hunting". See #54 for more details.

Multiple languages

Right now this is not a huge issue, but at least add functionality to the already existing button that shows the website is in English.

Card viewing problem with Redux

@jagger-harris brought this to my attention:

If a user clicks on a card and then goes to refresh, the site will land on an empty page (nothing has rendered).

Reason: Currently when someone clicks a card we push this cards data into the Redux store. Then, we route to a view proposal page that will take whatever card data is pushed into redux and display that data. The problem is, the Redux store will clear out completely upon page refresh (ie app re-render). So then we are still on this view proposal page, but Redux has no selected proposal now in its store and thus the page is completely gone.

Potential fix: One way to solve this problem (and eliminate the need for Redux) would be to create a mapping of Routes in app.jsx. For instance we would grab all the proposal data for the site (getAllProposals function) and then map each one of these values to a single route. That way we create an individual (and unique) URL for every single proposal we have. If someone is on a specific proposal (which has its own specific URL) and they refresh, they will end up back on that same page.

I do think it's neat using Redux to create one singular page that just filters what we see, instead of making a new page for every single proposal via a mapping. Maybe there could be a way to preserve Redux state through a refresh so that it doesn't get lost in the process? Just another potential idea.

IPFS shenanigans

IPFS implementation and other

  • Connect IPFS to wallet
  • Upload files to IPFS
  • Determine to use host or use Web3 Storage
  • Javascript (how to display IPFS text and images using hash)
  • Create dummy form and upload text from form to IPFS

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.