-
Notifications
You must be signed in to change notification settings - Fork 7
feat: goo (gno optimistic oracle) #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Left to do :
|
leohhhn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leaving a few comments
packages/r/intermarch3/goo/court.gno
Outdated
| type Vote struct { | ||
| RequestId string | ||
| Voter address | ||
| TokenAmount int64 | ||
| Hash string | ||
| Value int64 | ||
| Revealed bool | ||
| } | ||
|
|
||
| type Voter struct { | ||
| HasVoted bool | ||
| VoteIndex int64 | ||
| } | ||
|
|
||
| type Dispute struct { | ||
| RequestId string | ||
| Votes []Vote | ||
| NbResolvedVotes int64 | ||
| Voters *avl.Tree | ||
| IsResolved bool | ||
| WinningValue int64 | ||
| EndTime time.Time | ||
| EndRevealTime time.Time | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: could be in types.gno, since you already have a few.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 6ed3498
packages/r/intermarch3/goo/court.gno
Outdated
| } | ||
|
|
||
| var ( | ||
| Disputes = avl.NewTree() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be exported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not, could be used to follow initial request resolution on other contracts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
methods on exposed objects allow anyone to modify this object, for example here, anyone can call goo.Disputes.Set("eve", data)
if you want to expose this data safely, you should exposed a safe version, like a rotree wrapper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 31fc552
Fixed it by having this variable private, and the value is still accessible with getters.
packages/r/intermarch3/goo/README.md
Outdated
|
|
||
| ## Architecture | ||
|
|
||
| The oracle is composed of three main contracts: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's one contract though, isn't it? You just listed 3 files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my bad, wanted to say "3 main files"
✅ 6ed3498
| **2. Propose a Value** | ||
| ```bash | ||
| # Propose "Yes" (value 1) (replace ID with the actual ID returned from the RequestData call) | ||
| gnokey maketx call -pkgpath "gno.land/r/intermarch3/oo" -func "ProposeValue" -args "ID" -args "0" -gas-fee 1000000ugnot -gas-wanted 10000000 -send "2000000ugnot" -broadcast -chainid "dev" -remote "tcp://127.0.0.1:26657" <proposer-key-name> | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nice addition would be to suggest (and maybe even build) a Go program to suggest values using gnoclient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| table = append(table, renderRequest(value.(DataRequest))...) | ||
| return false | ||
| }) | ||
| msg += md.ColumnsN(table, 4, false) | ||
| if len(table) == 4 { | ||
| msg += md.Paragraph("No current requests.") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: you could probably add a newline here and there for readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 6ed3498
| } else { | ||
| if request.YesNoQuestion { | ||
| return resolveYesNo(*dispute) | ||
| } else { | ||
| return resolveNumeric(*dispute) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This else is useless, you can just put the logic in the function body after the error return above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 6ed3498
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this hasn't been fixed as far as i see
packages/r/intermarch3/goo/court.gno
Outdated
| func init() { | ||
| VoteToken = newOOToken("Gno Optimistic Oracle Token", "goot", 6) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: you can init this at the var block above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 6ed3498
leohhhn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
submitting some feedback
packages/r/intermarch3/goo/court.gno
Outdated
| if _, exists := disputes.Get(id); exists { | ||
| panic("error: Dispute for this request already exists.") | ||
| } | ||
| dispute := Dispute{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could set this as a pointer so that later you can simply fetch and change the object in place without having to set it again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 1dd0262
| // -- PUBLIC FUNCTIONS -- | ||
|
|
||
| // BuyInitialVoteToken allows a user to buy their first vote token by sending voteTokenPrice amount of ugnot. | ||
| func BuyInitialVoteToken(_ realm) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a heads up; gnot will be non-transferrable upon launch so you will not be able to use it to pay for things (usable only for gas)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its ok, we just need to set the price of the token to 0 ugnot at launch and change it after.
packages/r/intermarch3/goo/court.gno
Outdated
| } | ||
|
|
||
| // BalanceOfVoteToken returns the number of vote tokens held by the caller. | ||
| func BalanceOfVoteToken(_ realm) int64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you check out GRC20 Tellers? they're exposable so you do not have to have this kind of wrapper function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
packages/r/intermarch3/goo/court.gno
Outdated
| request := res.(DataRequest) | ||
| if request.Proposer == runtime.PreviousRealm().Address() || request.Disputer == runtime.PreviousRealm().Address() { | ||
| panic("error: Proposer and Disputer cannot vote in this dispute.") | ||
| } | ||
| if dispute.IsResolved { | ||
| panic("error: Dispute is already resolved.") | ||
| } | ||
| if time.Now().After(dispute.EndTime) { | ||
| panic("error: Vote period has ended.") | ||
| } | ||
| amount := VoteToken.BalanceOf(runtime.PreviousRealm().Address()) | ||
| if amount < 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newlines for readability
| request := res.(DataRequest) | |
| if request.Proposer == runtime.PreviousRealm().Address() || request.Disputer == runtime.PreviousRealm().Address() { | |
| panic("error: Proposer and Disputer cannot vote in this dispute.") | |
| } | |
| if dispute.IsResolved { | |
| panic("error: Dispute is already resolved.") | |
| } | |
| if time.Now().After(dispute.EndTime) { | |
| panic("error: Vote period has ended.") | |
| } | |
| amount := VoteToken.BalanceOf(runtime.PreviousRealm().Address()) | |
| if amount < 1 { | |
| request := res.(DataRequest) | |
| if request.Proposer == runtime.PreviousRealm().Address() || request.Disputer == runtime.PreviousRealm().Address() { | |
| panic("error: Proposer and Disputer cannot vote in this dispute.") | |
| } | |
| if dispute.IsResolved { | |
| panic("error: Dispute is already resolved.") | |
| } | |
| if time.Now().After(dispute.EndTime) { | |
| panic("error: Vote period has ended.") | |
| } | |
| amount := VoteToken.BalanceOf(runtime.PreviousRealm().Address()) | |
| if amount < 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
packages/r/intermarch3/goo/court.gno
Outdated
| caller := runtime.OriginCaller() | ||
| coins := banker.OriginSend() | ||
| if len(coins) != 1 || coins.AmountOf("ugnot") != voteTokenPrice { | ||
| panic("error: Must send exactly " + strconv.Itoa(int(voteTokenPrice/1_000_000)) + " gnot to get a vote token.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could be easier with ufmt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| "chain" | ||
| "chain/runtime" | ||
| ) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would you mind adding a short godoc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| } | ||
| } | ||
|
|
||
| func resolveYesNo(dispute Dispute) int64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above for godoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| var winningValue int64 | ||
| var weight int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be a var block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| winningValue = 0 | ||
| weight = noVotes | ||
| } | ||
| rewardAndSlachVoters(dispute, winningValue, weight) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: slach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| // Find the value with the most token weight | ||
| var winningValue int64 | ||
| var maxWeight int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| msg += md.HorizontalRule() | ||
|
|
||
| // List last 5 resolved requests and build table | ||
| msg += md.H2("Last 5 Resolved requests :") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| msg += md.H2("Last 5 Resolved requests :") | |
| msg += md.H2("Last 5 Resolved requests:") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
| // RequestData allows a user to request data from the oracle. | ||
| // `requesterReward` value needs to be sent to the contract as a reward | ||
| // You need to ask a question that can be answered with a single number like a yes/no question (0 or 1) or a specific value (e.g. ETH/USD price). | ||
| func RequestData(_ realm, ancillaryData string, yesNoQuestion bool, deadline int64) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be good to mention what the unit for the deadline is; seconds, a specific block, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
|
|
||
| id := idGenerator.Next().String() | ||
|
|
||
| request := DataRequest{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pointers in AVL Trees in general are better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 1dd0262
|
|
||
| coins := banker.OriginSend() | ||
| if len(coins) != 1 || coins.AmountOf("ugnot") != requesterReward { | ||
| panic("error: Incorrect reward amount sent. Required: " + strconv.FormatInt(requesterReward, 10) + " ugnot.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ufmt could be better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 3107cbe
leohhhn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few more comments, but overall this is good. Let's get the ball rolling on this more, it's super useful and really needed. Sorry for the slow turnaround on the review.
Description
In my journey to upskill on Gno.land, my first significant project is leveraging my knowledge of existing Ethereum smart contracts to implement an optimistic oracle, inspired by UMA Optimistic Oracle and their use in the well-known dApp Polymarket.
Here is a simplified implementation.
This was a previous pr on the gno repo (gnolang/gno#4681) that we moved here.