币安热点话题 DoraHacks 发起人...

DoraHacks 发起人 Eric Zhang: 用累进税系统缓解二次方资助中的不平等问题

Eric, Felix @DoraFactory

翻译贡献者: Yofu@DAOrayaki
原文 : Mitigate Quadratic Funding Inequality with a Progressive Tax System

二次方资助机制已经被许多主要的区块链生态广泛采用 : 以太坊、Filecoin、BSC、Solana、HECO、Flow 等。到目前为止,二次方资助机制被证明可以有效分配公共资金,以支持开源开软件项目 (Open Source Ventures) 和更通用的公共项目 (Public Goods)。

二次方资助机制允许人们进行多次投票,同时减少大户的影响。在最近的 DoraHacks Austin Web3 黑客马拉松中,二次方融资机制有效地限制了一次性大额捐赠的影响。(https://hackerlink.io/en/grant/Hack%20Austin/1)

到目前为止,主要的二次方融资资助平台(HackerLink, Gitcoin, clr.fund)都使用了 Vitalik Buterin 的文章《Quadratic Payments》中描述的算法。对二次方资助的一个中文的描述可以参考 Eric Zhang 的文章《二次方投票和二次方资助》(https://www.matataki.io/p/6113)。

该论文讨论了二次方资助过程,并概述了女巫攻击、共谋和选民激励等问题。截至目前,二次方资助平台一直在试图解决女巫攻击 (Sybil Attack) 和共谋 (Collusion) 的问题。HackerLink 正在新一版的二次方资助产品中使用 DoraID, DoraID 是来自 Dora Factory (DAO-as-a-Service 基础设施)的身份协议证明,提供基于质押的身份服务。Gitcoin 刚刚发布了其 GTC 治理代币和反女巫 Staking 机制。clr.fund 实现了 MACI。所有这些做法都很有前景,使得二次方投票和二次方资助可以在更大的场景中使用。

然而,还有一个很少被现有的文章和平台提及的问题,即匹配资金分配不平等的问题。

二次方资助中公共资金池分配的公平性问题

二次方资助在实践中放大了不平等问题。拥有多数选票的项目将获得更大比例的匹配池。在大多数情况下,这不仅会在分配资金时对早期项目造成不平等,还会抑制参与度(并有可能进一步鼓励女巫攻击,例如 Gitcoin GR9)。

在最近 HackerLink 上的 HECO Grant 中,排名第一的一个项目获得了大量的选票(>HECO Grant Round-1 总票数的 70%),并在当时得到了总匹配资金池的 95%。经过一些调查(数据分析),大多数捐款并非来自女巫攻击,而是来自于真实的投票。

在该项目以绝对优势占据排行榜后,HECO 的 Grant 在近两周内几乎没有收到任何提交,因为没有人认为自己可以与排名第一的项目竞争。最终,排名第一的项目团队宣布放弃不超过 50% 的匹配池配额,以支持本轮 Grant 中其他项目可以得到奖金池中的资助。最终,HECO Grant 决定将该项目的支持区(support area) 平均重新分配给所有获得投票 >=10 的项目。这是一个一次性的解决方案,但它启发了我们进一步解决不平等问题。

解决不平等问题最直接的机制是使用累进税制 (Progressive Taxation)。

累进税是第一次世界大战之前的一个重要的发明。它在 20 世纪的战后时期被广泛采用,并成为许多国家减少收入不平等的最重要机制之一。正如托马斯•皮凯蒂(Thomas Piketty)在其著作中所指出的那样,累进税「提供了一种方法,其限制工业资本主义造成的不平等,同时保持对私人财产和竞争力量的尊重」。

DoraHacks 发起人 Eric Zhang: 用累进税系统缓解二次方资助中的不平等问题一战前和二战后最高的收入所得税税率 (Source: One World in Data)

在二次方资助中,累进税制的实施有多种方法。当然,最简单的方法是设计一个静态累进税阶梯。每一轮之后,每个项目都要缴纳一定数额的税款到一个公共资金池。然后,公共资金池就可以按照社区认为公平的规则进行分配。

动态二次方累进税算法

这里,我们描述在每个 vote() 函数调用中动态重新分配财富的算法。

当项目获得投票时,我们定义支持区税率 $k$ 为 :

DoraHacks 发起人 Eric Zhang: 用累进税系统缓解二次方资助中的不平等问题

DoraHacks 发起人 Eric Zhang: 用累进税系统缓解二次方资助中的不平等问题

在这种情况下,对支持区征税,就可以防止垄断。我们可以对包含累进税收的二次方资助机制进行模拟。可以看到,累进税制平滑了公共资金的分配结果。在实际使用中,我们可以通过调节算法中的参数,改变税收曲线的形状,以达到公平性目标。

RULES ===================================

DoraHacks 发起人 Eric Zhang: 用累进税系统缓解二次方资助中的不平等问题

用于模拟的 Javascript 代码:

class Rule {
  constructor() {
    this.projects = []
    for (let i = 0; i < 10; i++) {
      this.projects[i] = {
        vote: 0,
        area: 0,
      }
    }

    this.area = 0
  }

  result() {
    for (let i = 0; i < this.projects.length; i++) {
      const p = this.projects[i]
      const s = (p.area / this.area * 10000).toFixed(2)

      const r = [this.area, p.area, p.vote]
      this.vote(i)
      const d = Number((p.area - r[1]).toFixed(2))
      const da = ((p.area / this.area * 10000) - Number(s)).toFixed(2)
      this.area = r[0]
      p.area = r[1]
      p.vote = r[2]

      console.log(`P${i + 1}: \t${r[2]} votes  \t${s} areas  \t${da} dA  \t${d} d`)
    }
  }
}

class OldRules extends Rule {
  vote(i) {
    const index = Math.min(i, this.projects.length - 1)
    const p = this.projects[index]
    this.area += p.vote
    p.area += p.vote
    p.vote += 1
  }
}

class Rules2 extends Rule {
  constructor() {
    super()
    this.top = 1
  }

  vote(i) {
    const index = Math.min(i, this.projects.length - 1)
    const p = this.projects[index]

    const k = Math.max(Math.min(1, (p.area - 5000) / this.top), 0)
      * p.area / Math.max(1, this.area)
    const added = p.vote * (1 - k)**2

    this.area += added
    p.area += added
    p.vote += 1

    if (p.area > this.top) {
      this.top = p.area
    }
  }
}

function test(rules, votes, ps) {
  for (let k = 0; k < votes.length; k++) {
    const v = votes[k]
    const p = ps[k]
    for (let n = 0; n < v; n++) {
      let i = 0
      while (p[i] && Math.random() > p[i]) {
        i++
      }
      rules.forEach(r => {
        r.vote(i)
      })
    }
  }
  rules.forEach((r, i) => {
    console.log(`RULES ${i + 1} ===================================`)
    r.result()
    console.log('')
  })
}

const AVERAGE = [1/10, 1/9, 1/8, 1/7, 1/6, 1/5, 1/4, 1/3, 1/2]
const BSC = [2/7, 1.8/6, 1.6/5, 1.4/4, 1.2/3, 1/2, 1/2, 1/2, 1/2]
const AMASS = new Array(9).fill(1/2)
const AAMASS = [0.76, ...new Array(8).fill(0.6)]
const BAMASS = [0.9, ...new Array(8).fill(0.6)]
const ATTACK = [0.01, 0.9, ...new Array(7).fill(1/2)]

test([
  new OldRules(),
  new Rules2(),
], [40000, 2000], [AAMASS, ATTACK])