探究Compound治理及構建治理介面

買賣虛擬貨幣
社羣治理已經取代了Compound協議管理員,這是朝著完全權力下放的重要一步。權力下放的主要目標是使協議能夠發展成為具有彈性的金融基礎設施,而沒有可知的弱點,也無需依賴任何團隊。透過這種方式,協議可以隨著整個加密生態系統的增長而繼續擴充套件,並且可以永久存在或至少伴隨著以太坊。本指南將向你介紹Compound的治理智慧合約,並逐步引導你構建與治理系統互動的自定義功能和介面。什麼是COMP?Compound協議只能由COMP代幣持有者及其代理升級和配置。協議的所有潛在更改,包括增加新市場或調整系統引數(如抵押因子或利率演算法),都必須透過治理智慧合約中指定的提案和投票過程。COMP是在 Compound 治理中具有 1:1 投票權的代幣。以太坊錢包中的COMP代幣持有人可以使用COMP 治理合約[1]中提供的函式將投票權委託給自己或任何其他以太坊地址。
委託投票權的接收者(稱為代理人),無論他們是COMP持有人本身還是其他地址,都可以提案、投票和執行提案以修改協議。你可以在Compound治理面板[2]上看到當前的代理列表。為了收到COMP,請在以太坊或任何測試網上使用Compound協議。有關更多詳細資訊,請查閱文件[3]。治理的核心概念一旦瞭解了基礎知識,就可以輕鬆構建用於治理的介面或擴充套件其功能。要更深入地瞭解治理,請檢視完整的文件[4]。為了快速入門,這裡僅列出關鍵概念。1. COMP - ERC-20代幣,用於指定使用者的投票權。使用者錢包中的COMP餘額越多,他們對提案的授權或投票就越重。2. Delegation委託 — COMP持有人只有在將投票權委託給某個地址後才能投票或建立提案。一次可以委託各一個地址,包括委託給COMP持有人自己的地址。被委託人的投票數相當於使用者賬號的 COMP 代幣餘額。投票將從當前區塊開始進行委託,直到傳送者再次委託或者轉移其 COMP。
3. Proposals提案 — 提案是可執行的程式碼,可修改協議及其工作方式。為了建立提案,必須至少有所有COMP的1%委託給該地址。現有總計1000萬個COMP,因此使用者必須將至少100,000個COMP委託給其地址。提案儲存在Governor智慧合約[5]的 “proposals” 對映[6]中。所有提案的投票期均為3天。如果提案者在整個投票期間未維持其投票權重,則任何人都可以取消該提案。4. Voting投票 — 使用者將投票權委託給其地址後,便可以對單個提案投票贊成或反對。提案處於“有效(Active)”狀態時可以進行投票。投票可以使用 castVote 立即提交,也可以使用 castVoteBySig 離線簽名稍後提交。如果大多數票(達到 4%的委託COMP的法定人數,即400,000 COMP)對某個提案投票贊成,則該提案將在時間鎖中排隊。5. Timelock時間鎖 — 所有治理和其他管理操作都必須在時間鎖中停留至少2天,然後才能在協議中實施。每個 cToken 合約和 Comptroller 合約都允許 Timelock 地址修改。Timelock 合約可以修改系統引數、邏輯和合約,以 "延遲時間、選擇退出" 的升級模式進行修改。

如果社羣決定以治理的形式對其進行升級,則隨著時間的推移,治理系統的這些關鍵元件可能會發生變化。COMP持有者將是該協議各個方面未來方向的最終仲裁者。

注:COMP 部署在0xc00e94cb662c3520282e6f5717214004a7f26888[7] 、 治理合約部署在0xc0dA01a04C3f3E0be433606045bB7017A7323E38[8]

透過Compound治理可以構建什麼?

應用程式開發人員可以構建自己的自定義工作流和介面,以促進其使用者和社羣參與Compound治理。例如,與Compound的利率市場整合的應用程式可能對新增治理功能感興趣,包括:

· 鼓勵使用者將COMP投票權委託給應用團隊的地址,以便該團隊可以代表使用者參與治理。
· 向使用者顯示特定的管理提案,以便擁有COMP的使用者可以直接對其投票。
· 向使用者提供透明的洞察力,以瞭解Compound的即將發生的潛在變化,包括新增新市場或其他升級的提案。

此類介面將需要以下元件的組合:

· 投票介面 - 使用者能對有效的提案進行投票。
· 委託介面 - 使用者將投票權委託給某個地址。
· 投票權排行榜 — 列出按投票權排序的投票地址。
· 我的代理投票介面 - 使用castVoteBySig 功能,使用者可以建立分配給其他使用者的投票。這將允許另一個使用者代理他們提交投票(並支付gas),而無需委託給另一個使用者。
· 提案資源管理器 - 在簡化的使用者介面中瀏覽過去或現在的治理提案。
· 提案建立介面 - 如果使用者有足夠的投票權重(> 1%),請選擇協議修改並初始化提案。

Compound 治理程式碼示例

治理介面必須在區塊鏈之間進行讀寫,我們將逐步介紹一些基本的JavaScript程式碼示例,以實現這兩種功能。讀取資料將使用Compound API和Web3完成。但是,只能使用Web3完成寫入操作,例如委託或投票。

我們將按順序演示如何執行以下每個操作:

· 獲取所有COMP代幣持有人
· 獲取所有委託
· 獲取所有提案
· 獲取所有提案的選票
· 委託投票權
· 對(有效)提案進行投票

GitHub上的Compound 治理快速入門[9]程式碼庫中提供了以下示例完整程式碼。

獲取所有COMP代幣持有人

讓我們根據其COMP餘額按降序獲取所有COMP代幣持有者。我們可以透過CompoundAPI的治理服務[10]來實現。

let requestParameters = {
  "page_size": 100,            // number of results in a page
  "network": "ropsten",        // mainnet, ropsten
  "order_by": "balance",       // "votes", "balance", "proposals_created"
  // "page_number": 1,         // see subsequent response's `pagination_summary` to specify the next page
  // addresses: ['0x123'],     // array of addresses to filter on
  // with_history: true,       // boolean, returns a list of transaction history for the accounts
};

requestParameters = '?' + new URLSearchParams(requestParameters).toString();

fetch(`https://api.compound.finance/api/v2/governance/accounts${requestParameters}`)
.then((response) => response.json())
.then((result) => {
  let accounts = result.accounts;
  console.log(accounts);
  let holders = [];
  accounts.forEach((account) => {
    holders.push({
      "address": account.address,
      "balance": parseFloat(account.balance).toFixed(4),
      "delegate": account.delegate.address == 0 ? 'None' : account.delegate.address
    });
  });

  holderListContainer.innerHTML = holderListTemplate(holders);
});

檔案:get_comp_holders_api.js [完整程式碼示例](https://github.com/compound-developers/compound-governance-examples/blob/master/api-examples/get_comp_holders.html "完整程式碼示例")

這段程式碼使用內建的瀏覽器獲取方法,該方法返回JavaScript Promise。程式碼庫有一個相同的示例,在示例中使用Web3.js對COMP持有人進行直接區塊鏈查詢[11]。我們可以使用COMP智慧合約找到相同的資訊。

這兩個程式碼示例的結果都是一個JSON物件陣列,其中包含帳戶地址,COMP代幣餘額和帳戶委託地址。

[
  {
    "address": "0xb61c5971d9c0472befceffbe662555b78284c307",
    "balance": "200000.0000",
    "delegate": "0xb61c5971d9c0472befceffbe662555b78284c307",
  }
]

comp-holder.json

獲取所有委託

我們可以看到委託了COMP的所有地址。下面是一個區塊鏈查詢,它利用COMP合約的DelegateVotesChanged 事件來收集當前的每個委託。

// Ropsten COMP Contract
const compAddress = '0x1fe16de955718cfab7a44605458ab023838c2793';
const compAbi = window.compAbi;
const comp = new web3.eth.Contract(compAbi, compAddress);

(async () => {
  const delegations = await comp.getPastEvents('DelegateVotesChanged', {
    fromBlock: 0,
    toBlock: 'latest'
  });

  const delegateAccounts = {};

  delegations.forEach(e => {
    const { delegate, newBalance } = e.returnValues;
    delegateAccounts[delegate] = newBalance;
  });

  const delegates = [];
  Object.keys(delegateAccounts).forEach((account) => {
    const voteWeight = +delegateAccounts[account];
    if (voteWeight === 0) return;
    delegates.push({
      delegate: account,
      vote_weight: voteWeight
    });
  });

  delegates.sort((a, b) => {
    return a.vote_weight < b.vote_weight ? 1 : -1;
  });

  delegates.forEach(d => {
    d.vote_weight = (100 * ((d.vote_weight / 1e18) / 10000000)).toFixed(6) + '%';
  });

  console.log(delegates);

  delegateListContainer.innerHTML = delegateListTemplate(delegates);
})();

get_delegates_web3.js [完整程式碼示例](https://github.com/compound-developers/compound-governance-examples/blob/master/web3-examples/get_delegates.html "完整程式碼示例")

或者,可以從Compound API 檢索此資訊。這是Compound API 示例[12]。這些示例建立一個JSON物件陣列,這些物件具有委託地址和COMP供給總量的投票權重(百分比)。

[
  {
    "delegate": "0xb61c5971d9c0472befceffbe662555b78284c307",
    "vote_weight": "2.000000%"
  }
]

delegate.json

獲取所有提案

如果你要建立治理瀏覽器,則獲取所有提案非常有用。Compound API 在這裡很方便。此示例將獲取所有提案,無論其狀態如何。該API能夠根據請求引數按狀態過濾提案。

let requestParameters = {
  "network": "ropsten",   // mainnet, ropsten
  "page_size": 100,       // integer, defaults to 10
  // "proposal_ids": 1,   // an integer ID or array of IDs
  // "state": "active",   //  "pending", "active", "canceled", "defeated", "succeeded", "queued", "expired", "executed"
  // "with_detail": true, // boolean
  // "page_number": 1,    // see subsequent response's `pagination_summary` to specify the next page
};

requestParameters = '?' + new URLSearchParams(requestParameters).toString();

fetch(`https://api.compound.finance/api/v2/governance/proposals${requestParameters}`)
  .then((response) => response.json())
  .then((result) => {
    console.log(result);
    const proposals = result.proposals || [];
    proposals.forEach((p) => {
      p.state = p.states[p.states.length-1].state
      p.for_votes = parseFloat(p.for_votes).toFixed(2);
      p.against_votes = parseFloat(p.against_votes).toFixed(2);
    });
    proposalListContainer.innerHTML = proposalItemTemplate(proposals);
  });

get_all_proposals_api.js [完整程式碼示例](https://github.com/compound-developers/compound-governance-examples/blob/master/api-examples/get_proposals.html "完整程式碼示例")

我們也可以使用治理合約的ProposalCreated事件直接透過Web3獲取相同的提案資料。程式碼示例使用以下提案資料建立一個JSON物件陣列。

[
  {
    "against_votes": "601000.00",
    "description": "10 BTC is actually a decent amount. Boop!",
    "for_votes": "835000.00",
    "id": 18,
    "title": "Reduce WBTC reserves by 10!",
    "state": "succeeded"
  }
]

proposal.json [完整程式碼示例](https://github.com/compound-developers/compound-governance-examples/blob/master/api-examples/get_proposals.html "完整程式碼示例")

獲取提案的選票

一旦提案達到“有效”狀態,選民就可以開始投票。選票公開儲存在區塊鏈上,因此我們可以隨時對其進行檢索。以下是在Ropsten上獲取提案1的提交投票的示例。

// Ropsten Governor Alpha Contract
const governanceAddress = '0xc5bfed3bb38a3c4078d4f130f57ca4c560551d45';
const governanceAbi = window.governanceAbi;
const gov = new web3.eth.Contract(governanceAbi, governanceAddress);

(async () => {
  const voteCastEvents = await gov.getPastEvents('VoteCast', {
    fromBlock: 0,
    toBlock: 'latest'
  });

  let submittedBallots = voteCastEvents;
  let formattedBallots = [];
  submittedBallots.forEach((ballot) => {
    const { voter, support, votes, proposalId } = ballot.returnValues;
    if (proposalId == id) {
      formattedBallots.push({
        blockNumber: ballot.blockNumber,
        address: voter,
        support: support ? 'In Favor' : 'Against',
        votes: (parseFloat(votes) / 1e18).toFixed(2),
      });
    }
  });

  formattedBallots.reverse();
  console.log(formattedBallots);

  ballotListContainer.innerHTML = ballotListTemplate(formattedBallots);
})();

get_all_ballots_web3.js

完整程式碼示例[13]

提案ID從1開始按升序排列。要檢視已提出的提案數量,可以從治理合約中獲取 proposalCount變數。選票可以從Compound API中獲取,例如在此治理服務示例[14]中。這是一個選票資料的JSON物件的結果陣列。

[
  {
    "address": "0x9687eb285292cba14a60a0c77dfd36dd95b93889",
    "support": "In Favor",
    "votes": "8500000.00"
  }
]

ballot.json

委託投票權

為了參與治理,COMP代幣持有者必須delegate委託其投票權。可以委託到任何地址,包括代幣持有者自己的地址。一次只能委託一個地址。

以下是設定委託地址的Web3示例。如果你沒有COMP代幣,則仍然可以委託,將來收到的COMP代幣將自動委託給你選擇的委託地址。

// Ropsten COMP Contract
compAddress = '0x1fe16de955718cfab7a44605458ab023838c2793';
compAbi = window.compAbi;
comp = new web3.eth.Contract(compAbi, compAddress);

let currentDelegate;
try {
  currentDelegate = await comp.methods.delegates(myAccount).call();
} catch (e) {
  currentDelegate = 0;
}

delegate.innerText = currentDelegate == 0 ? 'None' : currentDelegate;

submit.onclick = async () => {
  const delegateTo = newDelegate.value;

  if (!delegateTo) {
    alert('Invalid address to delegate your votes.');
    return;
  }

  loader.classList.remove('hidden');
  try {
    const tx = await comp.methods.delegate(delegateTo).send({ from: myAccount });
    console.log(tx);
    alert(`Successfully Delagated to ${delegateTo}`);
    window.location.reload();
  } catch(e) {
    console.error(e);
    alert(e.message);
  }
  loader.classList.add('hidden');
};

delegate.js

完整程式碼示例[15]

該程式碼依賴於啟用了Web3的瀏覽器。確保在瀏覽器中安裝MetaMask[16]。可以從水龍頭索取Ropsten ETH。實際效果如下:

對提案進行投票

Compound治理最激動人心的部分是在更改協議的提案中投下你的一票。委託者可以為每個有效的提案投反對票或贊成票。

以下程式碼示例展示了投票使用者介面的功能。如果Ropsten測試網上沒有活動的提案,那麼選擇器中將沒有任何提案!

// Ropsten Governor Contract
governanceAddress = '0xc5bfed3bb38a3c4078d4f130f57ca4c560551d45';
governanceAbi = window.governanceAbi;
gov = new web3.eth.Contract(governanceAbi, governanceAddress);

// Add a list of active proposals to the UI
getProposals();

// Get my account's vote weight
getMyVoteWeight(myAccount);

submit.onclick = async () => {
  // An active proposal needs to be selected in the UI
  if (proposalSelector.value < 1) {
    alert('Select a proposal to vote in.');
    return;
  }

  // A vote choice needs to be selected in the UI
  if (!_for.checked && !against.checked) {
    alert('Select a vote option.');
    return;
  }

  const proposal = proposalSelector.value;
  const vote = _for.checked ? true : false;

  loader.classList.remove('hidden');
  try {
    const tx = await gov.methods.castVote(proposal, vote).send({ from: myAccount });
    console.log(tx);
    alert(`Successfully voted ${vote ? 'for' : 'against'} Proposal ${proposal}`);
    window.location.reload();
  } catch(e) {
    console.error(e);
    alert(e.message);
  }
  loader.classList.add('hidden');
};

cast_vote.js

完整程式碼示例[17]

建立自己的治理介面

社羣治理的目標是使Compound協議成為對所有人開放和具有彈性的金融基礎設施。要達到這一里程碑,社羣、開發人員、使用者和機構都必須建立自己的介面和功能,以參與Compound治理。

由於以太坊具有可組合和開放訪問的特性,因此任何人和所有人都可以建立自己的COMP和治理專案。這裡有更多資源可以幫助你入門。

Compound治理資源

治理簡介(2020年2月)[18]
治理髮布公告(2020年4月)[19]
Compound協議治理文件[20]
Compound API 治理服務文件[21]
社羣主導的治理論壇[22]

參考資料

[1]COMP 治理合約: https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol
[2]Compound治理面板: https://compound.finance/governance
[3]文件: https://compound.finance/docs/governance
[4]文件: https://compound.finance/docs/governance
[5]Governor智慧合約: https://etherscan.io/address/0xc0da01a04c3f3e0be433606045bbbb7017a7323e38
[6]對映: https://learnblockchain.cn/docs/solidity/types.html#mapping-types
[7]0xc00e94cb662c3520282e6f5717214004a7f26888: https://etherscan.io/token/0xc00e94cb662c3520282e6f5717214004a7f26888
[8]0xc0dA01a04C3f3E0be433606045bB7017A7323E38:https://etherscan.io/address/0xc0dA01a04C3f3E0be433606045bB7017A7323E38
[9]Compound 治理快速入門: https://github.com/compound-developers/compound-governance-examples
[10]CompoundAPI的治理服務: https://compound.finance/docs/api#GovernanceService
[11]使用Web3.js對COMP持有人進行直接區塊鏈查詢: https://github.com/compound-developers/compound-governance-examples/blob/master/web3-examples/get_comp_holders.html
[12]Compound API 示例: https://github.com/compound-developers/compound-governance-examples/blob/master/api-examples/get_delegates.html
[13]完整程式碼示例: https://github.com/compound-developers/compound-governance-examples/blob/master/web3-examples/get_ballots.html
[14]治理服務示例: https://github.com/compound-developers/compound-governance-examples/blob/master/api-examples/get_ballots.html
[15]完整程式碼示例: https://github.com/compound-developers/compound-governance-examples/blob/master/web3-examples/set_delegate.html
[16]MetaMask: https://metamask.io/
[17]完整程式碼示例: https://github.com/compound-developers/compound-governance-examples/blob/master/web3-examples/cast_vote.html
[18]治理簡介(2020年2月): https://medium.com/compound-finance/compound-governance-5531f524cf68
[19]治理髮布公告(2020年4月): https://medium.com/compound-finance/compound-governance-decentralized-b18659f811e0
[20]Compound協議治理文件: https://compound.finance/docs/governance?ref=medium
[21]Compound API 治理服務文件: https://compound.finance/docs/api#GovernanceService?ref=medium
[22]社羣主導的治理論壇: https://compound.comradery.io/
[23]Cell Network: https://www.cellnetwork.io/?utm_souce=learnblockchain
[24]原文連結: https://medium.com/compound-finance/building-a-governance-interface-474fc271588c
[25]Adam Bavosa: https://medium.com/@adam.bavosa

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;