# Remove Miner

### Diagram Flow

<figure><img src="/files/t3mNvsCHN3cTkdw3xEEn" alt=""><figcaption></figcaption></figure>

### Complete Flow Influence

<figure><img src="/files/UCLzcJYjLi3K3gV1nzv4" alt=""><figcaption></figcaption></figure>

### Explanations

This is a smart contract that allows for the removal of a miner from the mining pool through an election vote using a threshold. The contract contains several functions that are used in the removal process.

The `propose-removal` function is called by a miner to propose the removal of another miner from the pool. The function first checks that the miner who initiated the proposal is currently in the mining pool, that the miner to be removed is also in the mining pool, and that the miner to be removed has not already been proposed for removal. If all of these conditions are met, the function adds the miner to be removed to a list of proposed removals.

Once a miner has been proposed for removal, other miners can vote on whether or not to remove them from the pool using the `vote-positive-remove-request` and `vote-negative-remove-request` functions. These functions check that the voter is not the miner being voted on, that the miner being voted on has been proposed for removal, and that the voter has not already voted. If these conditions are met, the function adds the vote to either the `map-votes-accept-removal` or `map-votes-reject-removal` map, depending on whether the vote is positive or negative.

The `process-removal` function is called once the threshold of positive votes is reached. This function removes the miner from the mining pool, updates the `miners-list` variable, and deletes the miner's entry in the `map-is-miner` map. The function also adds the miner to a blacklist to prevent them from rejoining the pool in the future. If the removal of the miner causes the new percentage of miners to fall below a critical threshold, the `update-threshold` function is called to adjust the threshold accordingly.

If  `N - threshold` negative votes for the removal action are reached, the `reject-removal` function is called. This function simply clears the votes for the miner and does not remove them from the pool.

There are several other helper functions in the contract, such as `has-voted-remove`, which checks if a miner has already voted, and `clear-votes-map-remove-vote`, which clears all votes for a specific miner. These functions are used throughout the contract to help manage the removal process.

### Smart Contract

```lisp
;; data stored
(define-constant err-not-in-miner-map (err u104))
(define-constant err-not-in-miner-map-miner-to-remove (err u114))
(define-constant err-already-proposed-for-removal (err u116))
(define-constant err-not-proposed-for-removal (err u117))
(define-constant err-cant-vote-himself (err u119))
(define-constant err-cant-remove-when-alone-in-pool (err u128))
(define-constant err-not-proposed-for-removal-k-missing (err u122))
(define-constant err-no-vote-permission (err u105))
(define-constant err-already-voted (err u108))

(define-map map-is-miner { address: principal } { value: bool })
(define-map map-block-proposed-to-remove { address: principal } { value: uint })
(define-map map-is-proposed-for-removal { address: principal } { value: bool })
(define-map map-remove-request-voter { miner-to-vote: principal, voter: principal } { value: bool })
(define-map map-votes-accept-removal { address: principal } { value: uint })
(define-map map-votes-reject-removal { address: principal } { value: uint })
(define-map map-blacklist { address: principal } { value: bool })

(define-data-var k uint u0)
(define-data-var n uint u1)


;; functions
(define-public (propose-removal (miner-to-remove principal))
(begin 
  (asserts! (not (is-eq (var-get n) u1)) err-cant-remove-when-alone-in-pool)
  (asserts! (check-is-miner-now tx-sender) err-not-in-miner-map) 
  (asserts! (check-is-miner-now miner-to-remove) err-not-in-miner-map-miner-to-remove)
  (asserts! (not (check-is-proposed-for-removal-now miner-to-remove)) err-already-proposed-for-removal) 
  (map-set map-block-proposed-to-remove {address: miner-to-remove} {value: block-height})
  (map-set map-is-proposed-for-removal {address: miner-to-remove} {value: true})
  (ok true)))

(define-public (vote-positive-remove-request (miner-to-vote principal))
(begin
  (asserts! (not (is-eq tx-sender miner-to-vote)) err-cant-vote-himself)
  (asserts! (check-is-proposed-for-removal-now miner-to-vote) err-not-proposed-for-removal) ;; map_is_proposed_for_removal
  (asserts! (is-ok (get-k-at-block-proposed-removal miner-to-vote)) err-not-proposed-for-removal-k-missing)
    (asserts! (unwrap! (check-is-miner-when-requested-remove miner-to-vote) err-cant-unwrap-check-miner) err-no-vote-permission)
    (asserts! (has-voted-remove miner-to-vote) err-already-voted) ;; O(1)
    (map-set map-remove-request-voter 
      {miner-to-vote: miner-to-vote, voter: tx-sender} 
      {value: true})
    (if (is-some (get value (map-get? map-votes-accept-removal {address: miner-to-vote}))) 
      (map-set map-votes-accept-removal {address: miner-to-vote} {value: (+ (unwrap-panic (get value (map-get? map-votes-accept-removal  {address: miner-to-vote}))) u1)})
      (map-set map-votes-accept-removal {address: miner-to-vote} {value: u1}))
    (some
      (if (is-vote-accepted (unwrap-panic (get value (map-get? map-votes-accept-removal {address: miner-to-vote}))) (unwrap-panic (get-k-at-block-proposed-removal miner-to-vote)))
        (process-removal miner-to-vote)
        (ok false)))
    (ok true)))

(define-public (vote-negative-remove-request (miner-to-vote principal))
(begin
  (asserts! (not (is-eq tx-sender miner-to-vote)) err-cant-vote-himself)
  (asserts! (check-is-proposed-for-removal-now miner-to-vote) err-not-proposed-for-removal) ;; map_is_waiting
  (asserts! (is-ok (get-k-at-block-proposed-removal miner-to-vote)) err-not-proposed-for-removal-k-missing)
  (asserts! (unwrap! (check-is-miner-when-requested-remove miner-to-vote) err-cant-unwrap-check-miner) err-no-vote-permission)
  (asserts! (has-voted-remove miner-to-vote) err-already-voted) ;; O(1)
  (map-set map-remove-request-voter 
    {miner-to-vote: miner-to-vote, voter: tx-sender} 
    {value: true})
  (if (is-some (get value (map-get? map-votes-reject-removal {address: miner-to-vote}))) 
    (map-set map-votes-reject-removal {address: miner-to-vote} {value: (+ (unwrap-panic (get value (map-get? map-votes-reject-removal {address: miner-to-vote}))) u1)})
    (map-set map-votes-reject-removal {address: miner-to-vote} {value: u1}))
  (some
    (if (is-vote-rejected-remove (unwrap-panic (get value (map-get? map-votes-reject-removal {address: miner-to-vote}))) (unwrap-panic (get-k-at-block-proposed-removal miner-to-vote)) (unwrap-panic (get-n-at-block-proposed-removal miner-to-vote)))
      (reject-removal miner-to-vote)
      (ok false)))
  (ok true)))

(define-private (process-removal (miner principal))
(begin 
  (let ((remove-result (unwrap-panic (remove-principal-miners-list miner)))
        (new-k-percentage (/ (* (var-get k) u100) (- (var-get n) u2))))
    (some (var-set miners-list remove-result))
    (var-set miner-to-remove-votes-remove miner)
    (var-set n (- (var-get n) u1))
    (map-delete map-is-miner {address: miner})
    (map-set map_blacklist {address: miner} {value: true})
    (clear-votes-map-remove-vote miner)
    (if (>= new-k-percentage (var-get k-critical)) 
      (update-threshold)
      false)
    (ok true))))

(define-private (reject-removal (miner principal))
(begin 
  (var-set miner-to-remove-votes-remove miner)
  (clear-votes-map-remove-vote miner)
  (ok true)))

(define-private (has-voted-remove (miner principal)) 
(not (if (is-some (get value (map-get? map-remove-request-voter {miner-to-vote: miner, voter: tx-sender})))
          (unwrap-panic (get value (map-get? map-remove-request-voter {miner-to-vote: miner, voter: tx-sender})))
          false
  )))

(define-private (clear-votes-map-remove-vote (miner principal)) 
(begin 
  (map-delete map-votes-accept-removal {address: (var-get miner-to-remove-votes-remove)})
  (map-delete map-votes-reject-removal {address: (var-get miner-to-remove-votes-remove)})
  (map-delete map-block-proposed-to-remove {address: (var-get miner-to-remove-votes-remove)})
  (map-delete map-is-proposed-for-removal {address: (var-get miner-to-remove-votes-remove)})
  (map remove-map-record-remove-vote (var-get miners-list))))

(define-private (remove-map-record-remove-vote (miner principal))
(if (is-some (map-get? map-remove-request-voter {miner-to-vote: (var-get miner-to-remove-votes-remove), voter: miner}))
  (map-delete map-remove-request-voter {miner-to-vote: (var-get miner-to-remove-votes-remove), voter: miner})
  false))

(define-private (get-k-at-block-proposed-removal (miner-to-vote principal)) 
(begin 
  (asserts! (is-some (get value (map-get? map-block-proposed-to-remove {address: miner-to-vote}))) err-not-proposed-for-removal)
  (at-block 
    (unwrap-panic 
      (get-block-info? id-header-hash 
        (unwrap-panic 
          (get value 
            (map-get? map-block-proposed-to-remove {address: miner-to-vote}))))) 
            (ok (var-get k)))))

(define-private (get-n-at-block-proposed-removal (miner-to-vote principal)) 
(begin 
  (asserts! (is-some (get value (map-get? map-block-proposed-to-remove {address: miner-to-vote}))) err-not-proposed-for-removal)
  (at-block 
    (unwrap-panic 
      (get-block-info? id-header-hash 
        (unwrap-panic 
          (get value 
            (map-get? map-block-proposed-to-remove {address: miner-to-vote}))))) 
            (ok (var-get n)))))
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.degenlab.io/decentralized-mining-pool/smart-contract/election-system/remove-miner.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
