# GitHub bounty oracle ## Project description We are building a service that allows for smart bounty execution on GitHub issues. The main advantage over other bounty programs [bounty source](https://www.bountysource.com/) is that it's fully decentralized and completely free for everyone. It allows for trustless execution of payments once the work has been done. ## User roles There will be up to 3 user roles involved: * Repository author (a.k.a. *owner*) * Issue creator * Issue resolver (a.k.a. *resolver*) Note: the issue could potentially be opened by either the owner or the resolver, in which case we only have 2 roles. ## User workflow: 1. An issue is opened in the owner's repository, requesting a new feature or a bug fix 2. If the owner decides the issue is worthy of a reward, he asks the smart contract to create a new bounty. **At this point the smart contract creates a reward promise that can only be claimed after closing the issue with a PR** 3. The resolver tracks down the Bounty: performs some work & opens a PR that is linked to the issue. 4. The owner reviews the code & merges the PR. **Once the PR is merged, the *resolver* can claim his reward by calling the smart contract** 5. *Resolver* calls the smart contract with his digital signature & payout address. Only authorized user will be able to claim the tokens. ## Components ### GitHub An open issue has a unique URL that will be used for two purposes: 1. As a key in the smart contract mapping to keep track of all open issues 2. As a message that the *resolver* will sign when submitting a claim to the smart contract When the *resolver* opens a PR, he provides his public key in the PR body. This will later be used as a security measure to protect un-authorised actors from claiming the reward. The *resolver* should ensure that his PR closes the issue by including a commit with msg such as `closes #33`. This will [automatically](https://github.blog/2013-01-22-closing-issues-via-commit-messages/) close the issue once that commit is merged into master. The owner will create a *Bounty* label in his repository that will allow easy filtering for issues eligible for a bounty. This simply serves as a convenience. No development needed for this component for the MVP - except for a good README write-up. ### smart contract The smart contract keeps track of bounties (hashmap). The bounty key is the hash of the issue URL and the value is the bounty payout value. The smart contract has two public methods: **Create** This creates a new entry in the hashmap. It requires the owner to lock up X tokens with the contract. These tokens can be unlocked only under two conditions: 1. The release method was called and executed successfully: tokens are transferred to the *resolver* 2. The bounty has expired and the tokens are returned to the *owner* It accepts the following parameters: * The amount of reward tokens * url to the GitHub issue * (optional) expiry date **Release** Should be called by the *resolver*. This will trigger a call to the Chainlink oracle that reaches out to GitHub & verifies the merge. There are two conditions for triggering the payout: 1. The oracle returns a successful response 2. The digital signature provided satisfies the verification, in particular: `verify(message, public_key, signature) = true` where: * `message` is the issue url * `public_key` was provided in the PR body * `signature` is the digital signature provided in the call parameter Parameters to the *release* method: * Issue url * PR url * digital `signature` * payout address ### *Resolver's* CLI The resolver needs to be able to provide his public key with the PR, as well as sign a message to generate a digital signature. These are standard cryptographic protocols and the tutorial will provide detailed instructions for the computation of these. ### ChainLink oracle The oracle acts as a data proxy between GitHub and the blockchain. When requested, it will query a github PR & issue, referenced by URLs provided with the call to the smart contract. It will check whether the issue has been closed with a commit [message](https://github.blog/2013-01-22-closing-issues-via-commit-messages/). If so, it will any PRs & then check whether that PR has been merged. If so, return `true`; else return `false` to the smart contract. If no PRs are referencing this issue, return `false`. The logic: 1. Get an [issue](https://docs.github.com/en/rest/reference/issues#get-an-issue). Verify that the issue is closed; else return `false`. 2. Look for [`closed`](https://docs.github.com/en/developers/webhooks-and-events/issue-event-types#closed) event type. If available, retrieve the commit ID of the *closing commit*; else return `false` 3. Get the [PR](https://docs.github.com/en/rest/reference/pulls#get-a-pull-request) & ensure it's merged. Retrieve the commit list. 5. Return `is_closing_commit_within_pr_commit_list(commit_ID, commit_list)` ### Substrate network We need a blockchain capable of deploying & executing smart contracts. Substrate will be the underlying blockchain, specifically the Edgeware network, which comes with the Contracts module as part of its runtime. ## Drawbacks & limitations * *resolver* still needs to go & claim the reward, i.e. it's not automatic * The usage is free, although there will still be transaction fees, inevitable for any blockchain, for making on-chain calls & transfers. * We must trust the *owner*. A dishonest bounty creator could wait for the PR, but rather than merge, choose to copy the code into the repo himself, thus abusing the work done by the *resolver* who won't get paid. * Decentralization assumes that we trust GitHub & its APIs * ... ## Future vision There is still a number of manual steps involved, potentially hindering the adoption of such a bounty model, in particular: 1. The call made by the *owner* after approving the bounty for an issue 2. Public key provision & digital signature generation by the *resolver* 3. The call needed to claim the reward To circumvent #1, a tighter integration with GitHub would be needed in order to provide automatic calls to the blockchain together with asset locking. If the *resolver* is able to provide his payment address inside the PR comments/description, another GitHub Workflow could trigger a call to the blockchain to transfer the funds upon merge. This call would require the authorization of the *owner*, rather than of the *resolver*. In this case, the *owner* would provide his private key to the GitHub Workflow as part of setting up the repository.The digital signature would be generated automatically upon merge. This approach would eliminate #2 & #3. ## Similar projects The project closest to ours is [StandardBounties](https://github.com/Bounties-Network/StandardBounties) on Ethereum. While they provide a larger array of functionalities (such as allowing co-founding from 3rd parties of existing bounties - something that could be included in the second iteration of this project), the bounty workflow is even further away from the usual developer experience. In particular: - the submissions are expected to be submitted as a file on IPFS & the verifier, introducting extra overhead to developers. - the bounty, as well as submissions metadata must be provided in the form of JSON We feel that by introducing Oracles which automatically verify PR merges, we successfully circumvent the need for IPFS & metadata tracking.