资助地址:
0xCd7da526f5C943126fa9E6f63b7774fA89E88d71
投票进展:DAO Committee 4/7 通过
赏金总量:75 USDC
研究种类:DAO, HackerLink, Progressive Taxation, Fairness
原文作者: Eric, Felix@DoraFactory
贡献者:Yofu, Eric @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)在其著作中所指出的那样,累进税“提供了一种方法,其限制工业资本主义造成的不平等,同时保持对私人财产和竞争力量的尊重”。
** 一战前和二战后最高的收入所得税税率 (Source: One World in Data)
在二次方资助中,累进税制的实施有多种方法。当然,最简单的方法是设计一个静态累进税阶梯。每一轮之后,每个项目都要缴纳一定数额的税款到一个公共资金池。然后,公共资金池就可以按照社区认为公平的规则进行分配。
根据公式,满足以下条件的项目将被征收重税:
该项目排名靠前
该项目在总支持区中占主导比例
在这种情况下,对支持区征税,就可以防止垄断。我们可以对包含累进税收的二次方资助机制进行模拟。可以看到,累进税制平滑了公共资金的分配结果。在实际使用中,我们可以通过调节算法中的参数,改变税收曲线的形状,以达到公平性目标。
RULES ===================================
用于模拟的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])
Go to "Discover" > "Top Stories" > "Wow"