Merge branch 'fix/token-formatting' of github.com:status-im/open-bounty into fix/token-formatting

This commit is contained in:
Vitaliy Vlasov 2018-03-12 17:55:47 +02:00
commit 9cd5ca84c4
No known key found for this signature in database
GPG Key ID: A7D57C347F2B2964
13 changed files with 323 additions and 262 deletions

View File

@ -23,7 +23,12 @@ RUN lein uberjar
FROM clojure FROM clojure
WORKDIR /root/ WORKDIR /root/
RUN apt-get update
RUN apt-get -y install xvfb
RUN apt-get -y install wkhtmltopdf
COPY --from=builder /usr/src/app/target/uberjar/commiteth.jar . COPY --from=builder /usr/src/app/target/uberjar/commiteth.jar .
COPY html2png.sh .
CMD [""] CMD [""]
ENTRYPOINT ["/usr/bin/java", "-Duser.timezone=UTC", "-Dconf=config-test.edn", "-jar", "/root/commiteth.jar"] ENTRYPOINT ["/usr/bin/java", "-Duser.timezone=UTC", "-Dconf=config-test.edn", "-jar", "/root/commiteth.jar"]

View File

@ -1,4 +1,5 @@
# Status Open Bounty # Status Open Bounty
[![Riot Chat Badge](https://img.shields.io/badge/join%20%23openbounty-riot-green.svg)](https://chat.status.im/#/room/#openbounty:status.im)
Allows you to set bounties for Github issues, paid out in Ether or any ERC-20 token. Allows you to set bounties for Github issues, paid out in Ether or any ERC-20 token.
@ -71,6 +72,7 @@ eth-account | Ethereum account ID for the bot
eth-password | Ethereum account password for the bot eth-password | Ethereum account password for the bot
eth-rpc-url | RPC URL to Ethereum node, e.g. Geth. Either local or remote eth-rpc-url | RPC URL to Ethereum node, e.g. Geth. Either local or remote
eth-wallet-file | Location of wallet file. If Geth is run with the parameters as given below, it will reside under `$HOME/.ropsten/keystore` eth-wallet-file | Location of wallet file. If Geth is run with the parameters as given below, it will reside under `$HOME/.ropsten/keystore`
offline-signing | Specifies whether to sign transactions locally before sending. Default is true. Set to false when connecting to local Geth node that unlocks accounts
tokenreg-base-format | Should be set to `:status` tokenreg-base-format | Should be set to `:status`
github-client-id | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps github-client-id | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps
github-client-secret | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps github-client-secret | Related to OAuth. Copied from GitHub account Settings->Developer settings->OAuth Apps
@ -91,14 +93,22 @@ Follow the steps [here](https://developer.github.com/apps/building-github-apps/c
## Running ## Running
### Geth ### Ethereum node
Launch a local geth node with the bot account unlocked: There are two options for connecting to an Ethereum node: either run a local node with an unlocked account, or connect to a remote Geth node or Infura. We will be connecting to Ropsten which is a test Ethereum network.
#### Local
In order to launch a local geth node with the bot account unlocked issue the following command:
``` ```
#!/bin/bash #!/bin/bash
geth --fast --testnet --cache=1024 --datadir=$HOME/.ropsten --verbosity 4 --port 50100 --ipcpath ~/.ropsten/geth.ipc --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpcapi db,eth,net,web3,personal --rpccorsdomain "https://wallet.ethereum.org" --unlock "0xYOUR_ADDR" --password <(echo "YOUR_PASSPHRASE") geth --fast --testnet --cache=1024 --datadir=$HOME/.ropsten --verbosity 4 --port 50100 --ipcpath ~/.ropsten/geth.ipc --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpcapi db,eth,net,web3,personal --rpccorsdomain "https://wallet.ethereum.org" --unlock "0xYOUR_ADDR" --password <(echo "YOUR_PASSPHRASE")
``` ```
#### Remote
Register at [Infura](https://infura.io/signup). You will receive an email with provider URLs. Paste an URL for the Ropsten network into `config.edn` under `:eth-rpc-url` key, and set `:offline-signing` to true.
### CSS auto-compilation ### CSS auto-compilation
Launch the following command in a separate shell: Launch the following command in a separate shell:

View File

@ -14,6 +14,9 @@
:eth-rpc-url "http://localhost:8545" :eth-rpc-url "http://localhost:8545"
:eth-wallet-file "/some/location" :eth-wallet-file "/some/location"
;; Specifies whether to sign transactions before sending. Should be false for local Geth, true for remote Infura
:offline-signing true
;; address of token registry to be used ;; address of token registry to be used
;; this is the default value for ropsten ;; this is the default value for ropsten
:tokenreg-addr "0x7d127a3e3b5e72cd8f15e7dee650abe4fcced2b9" :tokenreg-addr "0x7d127a3e3b5e72cd8f15e7dee650abe4fcced2b9"

3
html2png.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash -eu
# need to run wkhtmltoimage in quiet mode because it misuses stdout
xvfb-run -a -s "-screen 0 640x480x16" wkhtmltoimage -q "$@" 2>/dev/null

View File

@ -7,14 +7,65 @@
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[clojure.string :as str] [clojure.string :as str]
[pandect.core :as pandect] [pandect.core :as pandect]
[commiteth.util.util :refer [json-api-request]])) [commiteth.util.util :refer [json-api-request]])
(:import [org.web3j
protocol.Web3j
protocol.http.HttpService
protocol.core.DefaultBlockParameterName
protocol.core.methods.response.EthGetTransactionCount
protocol.core.methods.request.RawTransaction
utils.Numeric
crypto.Credentials
crypto.TransactionEncoder
crypto.WalletUtils]))
(defn eth-rpc-url [] (env :eth-rpc-url "http://localhost:8545")) (defn eth-rpc-url [] (env :eth-rpc-url "http://localhost:8545"))
(defn eth-account [] (:eth-account env)) (defn eth-account [] (:eth-account env))
(defn eth-password [] (:eth-password env)) (defn eth-password [] (:eth-password env))
(defn gas-estimate-factor [] (env :gas-estimate-factor 1.0)) (defn gas-estimate-factor [] (env :gas-estimate-factor 1.0))
(defn auto-gas-price? [] (env :auto-gas-price? false)) (defn auto-gas-price? [] (env :auto-gas-price false))
(defn offline-signing? [] (env :offline-signing true))
(defn wallet-file-path []
(env :eth-wallet-file))
(defn wallet-password []
(env :eth-password))
(defn creds []
(let [password (wallet-password)
file-path (wallet-file-path)]
(if (and password file-path)
(WalletUtils/loadCredentials
password
file-path)
(throw (ex-info "Make sure you provided proper credentials in appropriate resources/config.edn"
{:password password :file-path file-path})))))
(defn create-web3j []
(Web3j/build (HttpService. (eth-rpc-url))))
(defn get-signed-tx [gas-price gas-limit to data]
"Create a sign a raw transaction.
'From' argument is not needed as it's already
encoded in credentials.
See https://web3j.readthedocs.io/en/latest/transactions.html#offline-transaction-signing"
(let [web3j (create-web3j)
nonce (.. (.ethGetTransactionCount web3j
(env :eth-account)
DefaultBlockParameterName/LATEST)
sendAsync
get
getTransactionCount)
tx (RawTransaction/createTransaction
nonce
gas-price
gas-limit
to
data)
signed (TransactionEncoder/signMessage tx (creds))
hex-string (Numeric/toHexString signed)]
hex-string))
(defn eth-gasstation-gas-price (defn eth-gasstation-gas-price
[] []
(let [data (json-api-request "https://ethgasstation.info/json/ethgasAPI.json") (let [data (json-api-request "https://ethgasstation.info/json/ethgasAPI.json")
@ -40,6 +91,21 @@
(gas-price-from-config))) (gas-price-from-config)))
(gas-price-from-config))) (gas-price-from-config)))
(defn safe-read-str [s]
(if (nil? s)
(do
(log/error "JSON response is nil")
nil)
(try
(json/read-str s :key-fn keyword)
(catch Exception ex
(do (log/error "Exception when parsing json string:"
s
"message:"
ex)
nil)))))
(defn eth-rpc (defn eth-rpc
[method params] [method params]
(let [request-id (rand-int 4096) (let [request-id (rand-int 4096)
@ -49,8 +115,8 @@
:id request-id}) :id request-id})
options {:headers {"content-type" "application/json"} options {:headers {"content-type" "application/json"}
:body body} :body body}
response (:body @(post (eth-rpc-url) options)) response @(post (eth-rpc-url) options)
result (json/read-str response :key-fn keyword)] result (safe-read-str (:body response))]
(log/debug body "\n" result) (log/debug body "\n" result)
(if (= (:id result) request-id) (if (= (:id result) request-id)
@ -128,54 +194,16 @@
[account digits] [account digits]
(hex->eth (get-balance-hex account) digits)) (hex->eth (get-balance-hex account) digits))
(defn send-transaction
"Send transaction using default commiteth bot account."
[from to value & [params]]
(let [args (merge params
{:from from
:value value}
(when-not (nil? (gas-price))
{:gasPrice (integer->hex (gas-price))})
(when-not (contains? params :gas)
{:gas
(estimate-gas from to value params)}))]
(log/debug "args:" args)
(eth-rpc
"personal_sendTransaction"
[(if-not (nil? to)
(merge args {:to to})
args)
(eth-password)])))
(defn send-transaction-using-from-account
"Send transaction using account address in parameter from. Assumes
account has been unlocked."
[from to value & [params]]
(let [args (merge params
{:from from
:value value}
(when-not (nil? (gas-price))
{:gasPrice (integer->hex (gas-price))})
(when-not (contains? params :gas)
{:gas
(estimate-gas from to value params)}))]
(log/debug "args:" args)
(eth-rpc
"eth_sendTransaction"
[(if-not (nil? to)
(merge args {:to to})
args)])))
(defn get-transaction-receipt
[hash]
(eth-rpc "eth_getTransactionReceipt" [hash]))
(defn- format-param (defn- format-param
[param] [param]
(if (number? param) (if (number? param)
(format "%064x" param) (format "%064x" param)
(clojure.string/replace (format "%64s" (subs param 2)) " " "0"))) (clojure.string/replace (format "%64s" (subs param 2)) " " "0")))
(defn get-transaction-receipt
[hash]
(eth-rpc "eth_getTransactionReceipt" [hash]))
(defn format-call-params (defn format-call-params
[method-id & params] [method-id & params]
(let [params (join (map format-param params))] (let [params (join (map format-param params))]
@ -189,33 +217,30 @@
(defn execute (defn execute
[from contract method-id gas-limit & params] [from contract method-id gas-limit & params]
(let [data (apply format-call-params method-id params) (let [data (apply format-call-params method-id params)
value (format "0x%x" 0)] gas-price (gas-price)
(send-transaction from contract value (merge value (format "0x%x" 0)
{:data data} params (cond-> {:data data
(when gas-limit :from from
{:gas gas-limit}))))) :value value}
gas-price
(defn execute-using-addr (merge {:gasPrice (integer->hex gas-price)})
[from-addr from-passphrase contract method-id & params] contract
(eth-rpc "personal_unlockAccount" [from-addr from-passphrase 30]) (merge {:to contract}))
(let [data (apply format-call-params method-id params) gas (if gas-limit gas-limit
value (format "0x%x" 0)] (estimate-gas from contract value params))
(send-transaction-using-from-account from-addr params (if (offline-signing?)
contract (get-signed-tx (biginteger gas-price)
value (hex->big-integer gas)
{:data data}))) contract
data)
(defn transfer-eth (assoc params :gas gas))]
"Transfer amount-wei of ETH from from-addr to to-addr." (if (offline-signing?)
[from-addr from-passphrase to-addr amount-wei] (eth-rpc
(eth-rpc "personal_unlockAccount" [from-addr from-passphrase 30]) "eth_sendRawTransaction"
(let [data "0x" [params])
value (integer->hex amount-wei)] (eth-rpc
(send-transaction-using-from-account from-addr "personal_sendTransaction"
to-addr [params (eth-password)]))))
value
{:data data})))
(defn hex-ch->num (defn hex-ch->num
[ch] [ch]

View File

@ -1,8 +1,7 @@
(ns commiteth.eth.multisig-wallet (ns commiteth.eth.multisig-wallet
(:require [commiteth.eth.core :as eth] (:require [commiteth.eth.core :as eth
[commiteth.config :refer [env]]
[commiteth.eth.web3j
:refer [create-web3j creds]] :refer [create-web3j creds]]
[commiteth.config :refer [env]]
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[commiteth.eth.token-data :as token-data]) [commiteth.eth.token-data :as token-data])
(:import [org.web3j (:import [org.web3j
@ -191,30 +190,6 @@
[tla (token-balance bounty-addr tla)]))) addrs))) [tla (token-balance bounty-addr tla)]))) addrs)))
{}))) {})))
(defn transfer-tokens
"Transfer mount of given ERC20 token from from-addr to
to-addr. Connected geth needs to have keys for the account and
passphrase needs to be supplied. Returns transaction ID."
[from-addr from-passphrase token to-addr amount]
(let [token-addr (get-token-address token)]
(eth/execute-using-addr from-addr
from-passphrase
token-addr
(method-ids :transfer)
to-addr
amount)))
(defn get-owners
"Return vector of multisig owner addresses."
[bounty-addr]
(let [bounty-contract (load-bounty-contract bounty-addr)
owner-addresses (-> bounty-contract
(.getOwners)
.get)]
(if owner-addresses
(mapv #(.toString %) (.getValue owner-addresses))
[])))
(defn uint256 [x] (defn uint256 [x]
(org.web3j.abi.datatypes.generated.Uint256. x)) (org.web3j.abi.datatypes.generated.Uint256. x))

View File

@ -15,7 +15,7 @@
(defn update-data [] (defn update-data []
(let [test-data (env :testnet-token-data) (let [test-data (env :testnet-token-data)
token-data token-data
(if (and (env :on-testnet true) (if (and #_(env :on-testnet true)
test-data) test-data)
test-data test-data
(into {} (into {}

View File

@ -1,6 +1,5 @@
(ns commiteth.eth.token-registry (ns commiteth.eth.token-registry
(:require [commiteth.eth.core :as eth] (:require [commiteth.eth.core :as eth
[commiteth.eth.web3j
:refer [create-web3j creds]] :refer [create-web3j creds]]
[commiteth.config :refer [env]] [commiteth.config :refer [env]]
[clojure.tools.logging :as log]) [clojure.tools.logging :as log])

View File

@ -1,28 +0,0 @@
(ns commiteth.eth.web3j
(:require [commiteth.eth.core :as eth]
[commiteth.config :refer [env]])
(:import [org.web3j
protocol.Web3j
protocol.http.HttpService
crypto.Credentials
crypto.WalletUtils]))
(defn wallet-file-path []
(env :eth-wallet-file))
(defn wallet-password []
(env :eth-password))
(defn creds []
(let [password (wallet-password)
file-path (wallet-file-path)]
(if (and password file-path)
(WalletUtils/loadCredentials
password
file-path)
(throw (ex-info "Make sure you provided proper credentials in appropriate resources/config.edn"
{:password password :file-path file-path})))))
(defn create-web3j []
(Web3j/build (HttpService. (eth/eth-rpc-url))))

View File

@ -3,6 +3,7 @@
[core :as tentacles] [core :as tentacles]
[repos :as repos] [repos :as repos]
[oauth :as oauth] [oauth :as oauth]
[search :as search]
[users :as users] [users :as users]
[repos :as repos] [repos :as repos]
[issues :as issues] [issues :as issues]
@ -27,6 +28,8 @@
(defn on-testnet? [] (env :on-testnet)) (defn on-testnet? [] (env :on-testnet))
(defn webhook-secret [] (env :webhook-secret)) (defn webhook-secret [] (env :webhook-secret))
(defn authorize-url [scope] (defn authorize-url [scope]
(let [params (codec/form-encode {:client_id (client-id) (let [params (codec/form-encode {:client_id (client-id)
:redirect_uri (redirect-uri) :redirect_uri (redirect-uri)
@ -360,3 +363,32 @@
(let [[owner repo] (str/split full-repo #"/")] (let [[owner repo] (str/split full-repo #"/")]
(log/debug "creating bounty label" (str owner "/" repo) token) (log/debug "creating bounty label" (str owner "/" repo) token)
(issues/create-label owner repo "bounty" "fafad2" (auth-params token)))) (issues/create-label owner repo "bounty" "fafad2" (auth-params token))))
(defn get-labeled-issues-for-repos [repos auth-params]
"Find all issues with a bounty label in provided repos"
(let [get-last-part (fn get-last-part [s]
(subs s (inc (str/last-index-of s "/"))))
get-issue-info (fn get-issue-info [r issue]
(hash-map :owner r
:repo (get-last-part (:repository_url issue))
:id (:id issue)
:number (:number issue)
:title (:title issue)
:url (:html_url issue)
:created_at (:created_at issue)
:closed_at (:closed_at issue)))
issues (for [r repos]
(loop [repo-issues [] i 1]
(let [params (into auth-params
{:sort "created" :order "desc" :page i})
issues-page (-> (search/search-issues
nil
{:label "bounty" :user r :type "issue"}
params)
:items)]
(if (first issues-page)
(recur (into repo-issues
(map (partial get-issue-info r) issues-page))
(inc i))
repo-issues))))]
(apply concat issues)))

View File

@ -39,6 +39,7 @@
body (keywordize-keys (codec/form-decode (:body resp))) body (keywordize-keys (codec/form-decode (:body resp)))
scope (:scope body) scope (:scope body)
access-token (:access_token body)] access-token (:access_token body)]
(log/info "access-token:" access-token)
(log/debug "github sign-in callback, response body:" body) (log/debug "github sign-in callback, response body:" body)
(if (:error body) (if (:error body)
;; Why does Mist browser sends two redirects at the same time? The latter results in 401 error. ;; Why does Mist browser sends two redirects at the same time? The latter results in 401 error.

View File

@ -15,43 +15,50 @@
[clj-time.periodic :refer [periodic-seq]] [clj-time.periodic :refer [periodic-seq]]
[chime :refer [chime-at]])) [chime :refer [chime-at]]))
(defn update-issue-contract-address (defn update-issue-contract-address
"For each pending deployment: gets transaction receipt, updates db "For each pending deployment: gets transaction receipt, updates db
state (contract-address, comment-id) and posts github comment" state (contract-address, comment-id) and posts github comment"
[] []
(log/info "In update-issue-contract-address")
(doseq [{issue-id :issue_id (doseq [{issue-id :issue_id
transaction-hash :transaction_hash} (issues/list-pending-deployments)] transaction-hash :transaction_hash} (issues/list-pending-deployments)]
(log/debug "pending deployment:" transaction-hash) (log/info "pending deployment:" transaction-hash)
(when-let [receipt (eth/get-transaction-receipt transaction-hash)] (try
(log/info "update-issue-contract-address: transaction receipt for issue #" (when-let [receipt (eth/get-transaction-receipt transaction-hash)]
issue-id ": " receipt) (log/info "update-issue-contract-address: transaction receipt for issue #"
(if-let [contract-address (multisig/find-created-multisig-address receipt)] issue-id ": " receipt)
(let [issue (issues/update-contract-address issue-id contract-address) (if-let [contract-address (multisig/find-created-multisig-address receipt)]
{owner :owner (let [issue (issues/update-contract-address issue-id contract-address)
repo :repo {owner :owner
comment-id :comment_id repo :repo
issue-number :issue_number} issue comment-id :comment_id
balance-eth-str (eth/get-balance-eth contract-address 6) issue-number :issue_number} issue
balance-eth (read-string balance-eth-str)] balance-eth-str (eth/get-balance-eth contract-address 6)
(log/info "Updating comment image") balance-eth (read-string balance-eth-str)]
(bounties/update-bounty-comment-image issue-id (log/info "Updating comment image")
owner (bounties/update-bounty-comment-image issue-id
repo owner
issue-number repo
contract-address issue-number
balance-eth contract-address
balance-eth-str balance-eth
{}) balance-eth-str
(log/info "Updating comment") {})
(github/update-comment owner (log/info "Updating comment")
repo (github/update-comment owner
comment-id repo
issue-number comment-id
contract-address issue-number
balance-eth contract-address
balance-eth-str balance-eth
{})) balance-eth-str
(log/error "Failed to find contract address in tx logs"))))) {}))
(log/error "Failed to find contract address in tx logs")))
(catch Throwable ex
(do (log/error "update-issue-contract-address exception:" ex)
(clojure.stacktrace/print-stack-trace ex)))))
(log/info "Exit update-issue-contract-address"))
(defn deploy-contract [owner-address issue-id] (defn deploy-contract [owner-address issue-id]
@ -85,6 +92,7 @@
(defn self-sign-bounty (defn self-sign-bounty
"Walks through all issues eligible for bounty payout and signs corresponding transaction" "Walks through all issues eligible for bounty payout and signs corresponding transaction"
[] []
(log/info "In self-sign-bounty")
(doseq [{contract-address :contract_address (doseq [{contract-address :contract_address
issue-id :issue_id issue-id :issue_id
payout-address :payout_address payout-address :payout_address
@ -94,35 +102,42 @@
issue-number :issue_number issue-number :issue_number
balance-eth :balance_eth balance-eth :balance_eth
tokens :tokens tokens :tokens
winner-login :winner_login} (db-bounties/pending-bounties) winner-login :winner_login} (db-bounties/pending-bounties)]
:let [value (eth/get-balance-hex contract-address)]] (try
(if (empty? payout-address) (let [value (eth/get-balance-hex contract-address)]
(do (if (empty? payout-address)
(log/error "Cannot sign pending bounty - winner has no payout address") (do
(github/update-merged-issue-comment owner (log/error "Cannot sign pending bounty - winner has no payout address")
repo (github/update-merged-issue-comment owner
comment-id repo
contract-address comment-id
(eth-decimal->str balance-eth) contract-address
tokens (eth-decimal->str balance-eth)
winner-login tokens
true)) winner-login
(let [execute-hash (multisig/send-all contract-address payout-address)] true))
(log/info "Payout self-signed, called sign-all(" contract-address payout-address ") tx:" execute-hash) (let [execute-hash (multisig/send-all contract-address payout-address)]
(db-bounties/update-execute-hash issue-id execute-hash) (log/info "Payout self-signed, called sign-all(" contract-address payout-address ") tx:" execute-hash)
(db-bounties/update-winner-login issue-id winner-login) (db-bounties/update-execute-hash issue-id execute-hash)
(github/update-merged-issue-comment owner (db-bounties/update-winner-login issue-id winner-login)
repo (github/update-merged-issue-comment owner
comment-id repo
contract-address comment-id
(eth-decimal->str balance-eth) contract-address
tokens (eth-decimal->str balance-eth)
winner-login tokens
false))))) winner-login
false))))
(catch Throwable ex
(do (log/error "self-sign-bounty exception:" ex)
(clojure.stacktrace/print-stack-trace ex)))))
(log/info "Exit self-sign-bounty")
)
(defn update-confirm-hash (defn update-confirm-hash
"Gets transaction receipt for each pending payout and updates DB confirm_hash with tranaction ID of commiteth bot account's confirmation." "Gets transaction receipt for each pending payout and updates DB confirm_hash with tranaction ID of commiteth bot account's confirmation."
[] []
(log/info "In update-confirm-hash")
(doseq [{issue-id :issue_id (doseq [{issue-id :issue_id
execute-hash :execute_hash} (db-bounties/pending-payouts)] execute-hash :execute_hash} (db-bounties/pending-payouts)]
(log/info "pending payout:" execute-hash) (log/info "pending payout:" execute-hash)
@ -130,7 +145,8 @@
(log/info "execution receipt for issue #" issue-id ": " receipt) (log/info "execution receipt for issue #" issue-id ": " receipt)
(when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)] (when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)]
(log/info "confirm hash:" confirm-hash) (log/info "confirm hash:" confirm-hash)
(db-bounties/update-confirm-hash issue-id confirm-hash))))) (db-bounties/update-confirm-hash issue-id confirm-hash))))
(log/info "Exit update-confirm-hash"))
(defn update-watch-hash (defn update-watch-hash
@ -154,6 +170,7 @@
(defn update-payout-receipt (defn update-payout-receipt
"Gets transaction receipt for each confirmed payout and updates payout_hash" "Gets transaction receipt for each confirmed payout and updates payout_hash"
[] []
(log/info "In update-payout-receipt")
(doseq [{issue-id :issue_id (doseq [{issue-id :issue_id
payout-hash :payout_hash payout-hash :payout_hash
contract-address :contract_address contract-address :contract_address
@ -167,32 +184,38 @@
payee-login :payee_login payee-login :payee_login
updated :updated} (db-bounties/confirmed-payouts)] updated :updated} (db-bounties/confirmed-payouts)]
(log/debug "confirmed payout:" payout-hash) (log/debug "confirmed payout:" payout-hash)
(if-let [receipt (eth/get-transaction-receipt payout-hash)] (try
(let [contract-tokens (multisig/token-balances contract-address) (if-let [receipt (eth/get-transaction-receipt payout-hash)]
contract-eth-balance (eth/get-balance-wei contract-address)] (let [contract-tokens (multisig/token-balances contract-address)
(if (or contract-eth-balance (eth/get-balance-wei contract-address)]
(some #(> (second %) 0.0) contract-tokens) (if (or
(> contract-eth-balance 0)) (some #(> (second %) 0.0) contract-tokens)
(do (> contract-eth-balance 0))
(log/info "Contract still has funds") (do
(when (multisig/is-confirmed? contract-address confirm-id) (log/info "Contract still has funds")
(log/info "Detected bounty with funds and confirmed payout, calling executeTransaction") (when (multisig/is-confirmed? contract-address confirm-id)
(let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)] (log/info "Detected bounty with funds and confirmed payout, calling executeTransaction")
(log/info "execute tx:" execute-tx-hash)))) (let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)]
(log/info "execute tx:" execute-tx-hash))))
(do (do
(log/info "Payout has succeeded, saving payout receipt for issue #" issue-id ": " receipt) (log/info "Payout has succeeded, saving payout receipt for issue #" issue-id ": " receipt)
(db-bounties/update-payout-receipt issue-id receipt) (db-bounties/update-payout-receipt issue-id receipt)
(github/update-paid-issue-comment owner (github/update-paid-issue-comment owner
repo repo
comment-id comment-id
contract-address contract-address
(eth-decimal->str balance-eth) (eth-decimal->str balance-eth)
tokens tokens
payee-login)))) payee-login))))
(when (older-than-3h? updated) (when (older-than-3h? updated)
(log/info "Resetting payout hash for issue" issue-id "as it has not been mined in 3h") (log/info "Resetting payout hash for issue" issue-id "as it has not been mined in 3h")
(db-bounties/reset-payout-hash issue-id))))) (db-bounties/reset-payout-hash issue-id)))
(catch Throwable ex
(do (log/error "update-payout-receipt exception:" ex)
(clojure.stacktrace/print-stack-trace ex)))))
(log/info "Exit update-payout-receipt")
)
(defn abs (defn abs
"(abs n) is the absolute value of n" "(abs n) is the absolute value of n"
@ -213,17 +236,24 @@
(defn update-bounty-token-balances (defn update-bounty-token-balances
"Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts." "Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts."
[issue-id bounty-addr watch-hash] [issue-id bounty-addr watch-hash]
#_(log/info "In update-bounty-token-balances for issue" issue-id)
(doseq [[tla token-data] (token-data/as-map)] (doseq [[tla token-data] (token-data/as-map)]
(let [balance (multisig/token-balance bounty-addr tla)] (try
(when (> balance 0) (let [balance (multisig/token-balance bounty-addr tla)]
(do (when (> balance 0)
(log/debug "bounty at" bounty-addr "has" balance "of token" tla) (do
(let [internal-balance (multisig/token-balance-in-bounty bounty-addr tla)] (log/info "bounty at" bounty-addr "has" balance "of token" tla)
(when (and (nil? watch-hash) (let [internal-balance (multisig/token-balance-in-bounty bounty-addr tla)]
(not= balance internal-balance)) (when (and (nil? watch-hash)
(log/info "balances not in sync, calling watch") (not= balance internal-balance))
(let [hash (multisig/watch-token bounty-addr tla)] (log/info "balances not in sync, calling watch")
(db-bounties/update-watch-hash issue-id hash))))))))) (let [hash (multisig/watch-token bounty-addr tla)]
(db-bounties/update-watch-hash issue-id hash)))))))
(catch Throwable ex
(do (log/error "update-bounty-token-balances exception:" ex)
(clojure.stacktrace/print-stack-trace ex)))))
#_(log/info "Exit update-bounty-token-balances"))
(defn update-contract-internal-balances (defn update-contract-internal-balances
"It is required in our current smart contract to manually update it's internal balance when some tokens have been added." "It is required in our current smart contract to manually update it's internal balance when some tokens have been added."
@ -263,6 +293,7 @@
(defn update-balances (defn update-balances
[] []
(log/info "In update-balances")
(doseq [{contract-address :contract_address (doseq [{contract-address :contract_address
owner :owner owner :owner
repo :repo repo :repo
@ -271,43 +302,48 @@
db-balance-eth :balance_eth db-balance-eth :balance_eth
db-tokens :tokens db-tokens :tokens
issue-number :issue_number} (db-bounties/open-bounty-contracts)] issue-number :issue_number} (db-bounties/open-bounty-contracts)]
(when comment-id (try
(let [balance-eth-str (eth/get-balance-eth contract-address 6) (when comment-id
balance-eth (read-string balance-eth-str) (let [balance-eth-str (eth/get-balance-eth contract-address 6)
token-balances (multisig/token-balances contract-address)] balance-eth (read-string balance-eth-str)
(log/debug "update-balances" balance-eth token-balances (multisig/token-balances contract-address)]
balance-eth-str token-balances owner repo issue-number) (log/debug "update-balances" balance-eth
balance-eth-str token-balances owner repo issue-number)
(when (or (when (or
(not (float= db-balance-eth balance-eth)) (not (float= db-balance-eth balance-eth))
(not= db-tokens token-balances)) (not= db-tokens token-balances))
(log/debug "balances differ") (log/debug "balances differ")
(log/debug "ETH (db):" db-balance-eth (type db-balance-eth) ) (log/debug "ETH (db):" db-balance-eth (type db-balance-eth) )
(log/debug "ETH (chain):" balance-eth (type balance-eth) ) (log/debug "ETH (chain):" balance-eth (type balance-eth) )
(log/debug "ETH cmp:" (float= db-balance-eth balance-eth)) (log/debug "ETH cmp:" (float= db-balance-eth balance-eth))
(log/debug "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens))) (log/debug "tokens (db):" db-tokens (type db-tokens) (type (:SNT db-tokens)))
(log/debug "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances))) (log/debug "tokens (chain):" token-balances (type token-balances) (type (:SNT token-balances)))
(log/debug "tokens cmp:" (= db-tokens token-balances)) (log/debug "tokens cmp:" (= db-tokens token-balances))
(issues/update-eth-balance contract-address balance-eth) (issues/update-eth-balance contract-address balance-eth)
(issues/update-token-balances contract-address token-balances) (issues/update-token-balances contract-address token-balances)
(bounties/update-bounty-comment-image issue-id (bounties/update-bounty-comment-image issue-id
owner owner
repo repo
issue-number issue-number
contract-address contract-address
balance-eth balance-eth
balance-eth-str balance-eth-str
token-balances) token-balances)
(github/update-comment owner (github/update-comment owner
repo repo
comment-id comment-id
issue-number issue-number
contract-address contract-address
balance-eth balance-eth
balance-eth-str balance-eth-str
token-balances) token-balances)
(update-issue-usd-value contract-address)))))) (update-issue-usd-value contract-address))))
(catch Throwable ex
(do (log/error "update-balances exception:" ex)
(clojure.stacktrace/print-stack-trace ex)))))
(log/info "Exit update-balances"))
(defn wrap-in-try-catch [func] (defn wrap-in-try-catch [func]
@ -323,7 +359,7 @@
(defn run-1-min-interval-tasks [time] (defn run-1-min-interval-tasks [time]
(do (do
(log/debug "run-1-min-interval-tasks" time) (log/info "run-1-min-interval-tasks" time)
;; TODO: disabled for now. looks like it may cause extraneus ;; TODO: disabled for now. looks like it may cause extraneus
;; contract deployments and costs ;; contract deployments and costs
(run-tasks (run-tasks