ERC
ERC
什么是以太坊的ERC?
ERC是Ethereum Request for Comments的首字母缩写。它就像技术文档,定义了适用于一群想要利用以太坊生态系统的开发者和用户的方法、行为、创新和研究。
你可能想知道谁有权力创建和管理ERC。以太坊的智能合约程序员负责编写ERC相关文件,以描述每个基于以太坊的Token必须遵守的一系列规则。他们还经常审查这些文件,并对其进行评论以进一步改进。
要轻松理解ERC,可以考虑成立一个工程任务组,向开发人员传达技术说明和规则,如果每个人都想利用特定生态系统的好处,那么他们都需要遵守这些技术说明和规则。
什么是ERC代币标准?
ERC代币标准解释了所有建立在以太坊区块链上的ERC代币的某些规则。以太坊的社区会适当审查这套规则,并根据不断变化的要求进行修订。此外,ERC标准的设计是为了让ERC代币能够无缝互动。
ERC-20、ERC-721和ERC-1155作为三种流行的ERC代币标准或协议出现,在各大行业都有其应用。以太坊社区完全批准了这些代币标准,它们在具体特征和功能方面有所不同。
在了解代币标准的具体含义或工作原理之前,我们首先应该了解以太坊上智能合约标准的要点。以下语句对其进行了定义。
- 智能合约描述了智能合约程序员应遵守的规则,以利用以太坊网络的潜在优势。
- 这些标准适用于支持智能合约和去中心化应用(dApps)开发的区块链。
- 智能合约标准包含代币标准、库的主题与格式、名称注册和相关细节。
ERC代币标准只是智能合约标准的另一个名称。以太坊上的智能合约必须遵守标准或规则,以实现代币创建、交易处理、支出等基本功能。通过引入改进的ERC标准,以太坊释放了其生态系统的真正潜力,并授权开发更具体的智能合约,促进网络的增长。
ERC-20代币标准
ERC-20在2015年首次被提出,两年后的2017年,最终融入以太坊生态系统。ERC-20介绍了在以太坊区块链上创建可互换代币的代币标准。简单地说,ERC-20由支持开发相同代币的属性组成。
例如,表示货币的ERC-20代币可以像以太坊的原生货币–以太币一样工作。这意味着1个代币将永远等于另一个代币的价值,并且可以相互交换。ERC 20代币为可替换代币的发展设定了标准,但可替换代币实际上能代表什么?让我们来看看它们。
- 任何在线平台的信誉值。
- 彩票和计划。
- 金融资产,如公司的股份、红利和股票。
- 法定货币,包括美元。
- 黄金盎司,以及更多…
以太坊需要一个强大的标准来实现整个运营的统一,以支持代币开发并在区块链网络上对其进行监管。这就是为什么ERC-20可以进入游戏领域。
去中心化世界的开发者为了不同的目的,广泛使用ERC-20代币标准,比如开发可互操作的代币应用,与以太坊生态系统中的其他产品和服务兼容。
ERC-20代币的特点
- ERC 20代币是 “可替代性代币 “的另一个名称。
- 可替代性定义了资产或代币兑换相同价值资产的能力,例如两张1美元纸币。
- 无论其特征和结构如何,每个ERC-20代币都严格等同于相同的价值。
- ERC代币最受欢迎的应用领域是稳定币、治理代币和ICO。
ERC-721:不可互换的代币
要了解ERC-721标准,你必须首先了解NFTs(不可替代的代币)。看看我们解释NFTs的详细见解,以及它们在区块链的去中心化世界中的作用。
Cryptokitties(广为流传的非同质化代币)的创始人、CTO Dieter Shirley最初提议开发一种新的代币类型来支持NFTs。该提案将于2018年晚些时候获得批准。它专门用于NFTs,这意味着遵守ERC-721的规则开发的代币可以代表以太坊区块链上任何数字资产的价值。
至此,我们得出结论:如果ERC-20对于发明新的加密货币至关重要,那么ERC-721对于代表某个人对这些数字资产所有权的证明来说是很有价值的。ERC-721可以表示以下内容:
- 一个独特的数字艺术品
- 推文和社交媒体文章
- 游戏中的收藏品
- 游戏人物
- 任何卡通人物和数以百万计的其他NFTs….
这种特殊类型的代币为利用NFTs的企业带来了惊人的可能性。同样,ERC-721也为他们带来了挑战,为了应对这些挑战,ERC-721标准开始发挥作用。
请注意,每个NFTs都有一个uint256变量,称为tokenId。因此,对于每个EBR-721合同,合同地址键值对 uint256 tokenId必须是唯一的。
此外,dApps还应该有一个 “converter”来调节NFTs的输入和输出过程。例如,converter将tokenId视为输入,并输出不可伪造的代币,如僵尸图像、杀戮、游戏收藏品等。
ERC-721代币的特点
- ERC-721代币是不可伪造的代币(NFTs)的标准。
- 这些代币不能被兑换成同等价值的东西,因为它们是独一无二的。
- 每个ERC-721代表各自NFT的价值,可能有所不同。
- ERC-721代币最受欢迎的应用领域是游戏中的NFTs。
ERC-777代币标准
类似于 ERC20,ERC777 是一种同质化代币的标准,其重点在于允许在交易代币时进行更复杂的交互。更广泛地说,它通过提供等效于 msg.value 字段的东西(但用于代币),使代币和以太币更紧密地结合在一起。
该标准还带来了多个生活质量方面的改进,例如消除了围绕 decimals 的混淆,使用适当的事件进行铸造和销毁等等,但其杀手级功能是接收Hook。Hook仅仅是合约中的一个函数,当代币被发送到该合约时会被调用,这意味着账户和合约可以对接收代币做出反应。
这实现了许多有趣的用例,包括使用代币进行原子购买(无需在两个单独的交易中执行 approve 和 transferFrom),拒绝接收代币(通过在Hook调用中回滚),将接收到的代币重定向到其他地址(类似于[PaymentSplitter的做法)等等。
此外,由于合约需要实现这些Hook才能接收代币,因此没有代币会卡在不知道 ERC777 协议的合约中,就像在使用 ERC20 时发生过无数次一样。
ERC-1155:多代币标准
结合ERC-20和ERC-720的能力,Witek Radomski(Enjin的首席技术官)为Ethereum智能合约引入了一个包罗万象的代币标准。这是一个标准接口,支持开发同质化的、半同质化的、非同质化的代币和其他配置的通用智能合约。
现在,您可以使用单个接口满足所有代币开发需求并解决问题,从而使ERC-1155成为游戏规则的改变者。这样一个独特的代币标准的想法是开发一个强大的智能合约接口,代表和管理不同形式的ERC代币。
ERC-1155的另一个优点是,它改善了以前ERC代币标准的整体功能,使以太坊生态系统更加高效和可扩展。
ERC-1155代币的特点
- ERC-1155是一个智能合约接口,代表同质化的、半同质化的和非同质化的代币。
- ERC-1155可以执行ERC-20和ERC-720的功能,甚至可以同时执行两者。
- 每个代币都可以根据代币的性质代表不同的价值;同质化的、半同质化的和非同质化的。
- ERC-1155适用于创建NFT、可兑换购物券、ICO等。
ERC165标准
- 一种接口检测查询和发布标准
- 更具体的说是一种可以查询目标合约是否支持了特定的接口,当然同时你也可以发布自己实现的接口,以供他人查询和交互。
ERC165有什么用?
可以通过其确定一个合约支持哪些接口,这样就知道如何与它进行交互。
例子:
如对于NFT市场来说,就可以通过ERC165标准来查询你的智能合约是不是实现了ERC721接口,如果是的话就可以使用ERC721的各种方法与你的合约进行交互和操作。
所以ERC165提供了一种确定性的互操作支持。
ERC-1967
透明可升级代理是一种设计模式,用于在升级代理的同时消除函数选择器冲突的可能性。
一个功能齐全的以太坊代理至少需要以下两个特性:
- 一个存储槽,保存实现合约的地址
- 一个机制,允许管理员更改实现地址
ERC-1967标准规定了实现地址应存储的位置,以最小化存储碰撞的机会。然而,ERC-1967 标准并没有规定如何更改实现地址。
将一个额外的函数放置在代理中以更改实现(例如 updateImplementation(address _newImplementation))的问题在于,更新函数有非忽略的机会与实现中的某个函数发生冲突。
作用:
- 防止存储冲突
- 升级安全可验证
可升级合约:代理
主要涉及ERC-1967、ERC-1822、ERC-1167、ERC-2535
Q&A:
为什么存在这种模式:
对于”代理”来说,它来源于智能合约一经上链是不可变的。虽然这有助于实现去中心化和安全性,但它可能会降低智能合约的功能性。合约不可变将会阻止合约部署后对业务逻辑的任何更新。在代理出现之前,解决这种问题的方法是通过”合约迁移“来解决的。合约的新版本将被部署,并且所有状态和余额将需要被转移到这个新实例。显然,这种方法的一个明显缺点是,新部署会导致新的合约地址。对于继承到更广泛生态系统中的应用程序,这将要求所有第三方也更新其代码库以指向新合约。简单点来说,就是“合约迁移”会导致旧的数据都要转移到新的合约中。这很不利于大型项目的更新和维护。另一个缺点是将状态和余额转移到这个新实例的操作复杂性。这不禁会在Gas方面非常昂贵,而且这还将是一个非常敏感的操作。不正确地更新新合约的状态可能会破坏功能并导致安全漏洞。
因此出现了一种更简单的解决方案,即在不更改合约地址的情况下更新合约的基础逻辑,实现最小化操作开销。这就是代理模式的由来。使用代理模式创建的可升级智能合约使开发者能够在部署后修改合约功能——而不会损害安全性或去中心化。
代理模式的发展:
最初的代理成为委托代理。这是通过两个合约分别实现业务逻辑和数据存储。“代理合约”用于数据,”实现合约(逻辑合约)“用于业务逻辑。据此,我们可以利用“代理合约”从“实现合约”中访问和使用业务逻辑,以“代理”的存储上下文。“代理”的回退函数将使用委托调用。回退函数(fallback)是在合约上调用不存在的函数时执行的函数。这允许合约响应任意以太坊交易。但是委托代理的出现同时也带来了新的问题,主要是两个合约之间的冲突——存储槽冲突和函数签名冲突。
存储冲突
在 Solidity 中,存储布局由代码中变量声明的顺序确定。在升级过程中对此顺序的更改可能导致存储冲突 ,其中数据被错误地读取或覆盖。广义上说,这些冲突可以分为两种类型:
“代理”和“实现”之间的存储冲突
代理模式要求“代理”和其“实现合约”共享相同的存储布局。如果不匹配,可能会导致存储冲突。
存储冲突是指两个不同的合约在相同的存储槽上分配了相同的变量。这可能导致变量被错误地读取或覆盖。
“实现”的不同版本之间的存储冲突
- 当升级“实现合约“时,状态变量的顺序或类型的更改可能会导致存储槽被重新分配。
函数签名冲突
在合约内部选择函数是由 4 字节的函数签名确定的。这些签名是从函数的名称和其输入类型派生的。这些签名的冲突可能会导致函数调用的歧义和安全漏洞。
例如让我们来看 burn(uint256) 和 collate_propagate_storage(bytes16) 的函数签名。
- burn(uint256) = 0x42966c68
- collate_propagate_storage(bytes16) = 0x42966c68
请注意,完整的哈希值是不同的,但这并不重要,因为我们只需要前 4 个字节匹配。
还有一种情况是两个合约如果存在相同的函数,当用户尝试调用此函数时,合约无法知道你打算调用哪个合约的函数。这种歧义可能会导致意外错误甚至恶意利用。
为了解决这个问题,出现了一个新的代理来解决这个确切的问题,即透明代理。透明代理的核心思想是为管理员用户和非管理员用户提供2条不同的执行路径。如果管理员调用“代理合约”,函数将可用。对于其他人,所用调用都将通过回退函数委托给“实现合约”,即使“代理合约”中也存在与之想匹配的函数签名。这就避免了函数签名冲突,管理员可以与“代理合约”中的函数交互,而非管理员只能与“实现合约”交互。但是这也有一个缺点,就是普通用户将无法再访问“代理合约”的存储数据。例如,访问“实现合约”地址的
getter函数。他们必须使用web3.eth.getStorageAt(),而getStorageAt()的问题在于你需要知道存储中的位置。 然而,透明代理并不是代理模式的最后一次迭代,还有一个我们需要审查的。应该关注透明代理的 gas 使用。在“代理合约”中引入了管理员检查意味着管理员需要在每次调用时从存储中加载。而从存储中加载是EVM最昂贵的操作码之一。用户的 gas 开销(因此成本增加)导致了 UUPS 代理(通用可升级代理标准)的开发。
UUPS 代理的关键区别在于将“代理”合约中的“upgradeToAndCall”逻辑从“代理”合约移动到“实现”合约。这个变化意味着“代理合约”只是通过委托调用简单地将所有调用转发到“实现合约“。现在授权在“实现合约”中,我们不再需要 ProxyAdmin 合约,并且我们减少了每次调用“代理”时检查
msg.sender是否为“管理员”的 gas 开销。相反,授权逻辑和随后的管理员地址的 gas 昂贵 SLOAD 只在调用 upgradeToAndCall 时执行。因此,所有非管理员用户调用都避免了这个SLOAD。 OpenZepplin 提供了一个抽象的 UUPS 合约 ,可以作为你的“实现”的基础。它留下一个未定义函数
_authorizeUpgrade(address newImplementation)(必须在“实现”合约中实现自定义_authorizeUpgrade),以便你作为开发人员可以实现自己的自定义升级授权方式。这些特性可以被实现为诸如时间锁升级、多重签名升级等功能。即使是UUPS代理也有优势和劣势
主要优势如下:
- 减少了用户的 gas 开销。
- 消除了 ProxyAdmin 合约的需要。
- upgradeAndCall 逻辑本身变得可升级,因为它在实现中,而实现可以被升级。这包括最终删除它并确立合约的当前状态。
劣势包括:
- 减少了关注点的分离,你的实现合约现在处理你的授权升级逻辑和业务逻辑。
- 更新实现合约时增加了风险。由于你的实现现在包含了你的授权升级逻辑,每次升级都可能改变你的授权升级逻辑的攻击面。
- 代理“变砖”的风险。如果不小心升级了不包含 upgradeAndCall 函数的实现合约,代理的升级功能将永远丢失。
在实践中看到的两种代理概念:最小代理(也称为克隆)和信标代理。
最小代理:
最小代理的概念是为部署共享公共逻辑但需要单独存储的合约的多个实例提供了一种简化的方法。一个例子是 Gnosis Safe 合约,其中每个 Safe 都是独特的,但底层的多签逻辑保持一致。与为每个新实例重新部署整个逻辑相比,这是一种耗费 gas 且昂贵的方法,最小代理模式涉及部署单个实现合约,然后为每个新实例创建轻量级代理合约。最小代理不包括可升级性或授权功能,简化了它们的结构,并减少了部署和运行时的 gas 成本。它们一旦部署就是静态且不可变的。信标代理模式为需要同步更新的多个代理合约引入了一种高效的升级机制。该设计利用了一个名为“信标(Beacon)”的单独合约,该合约保存了所有关联代理使用的实现地址。然后,每个“代理”只需查询“信标”以检索当前的实现地址,而不是自己保存它。
信标代理:
信标代理模式为需要同步更新的多个代理合约引入了一种高效的升级机制。该设计利用了一个名为“信标(Beacon)”的单独合约,该合约保存了所有关联代理使用的实现地址。然后,每个“代理”只需查询“信标”以检索当前的实现地址,而不是自己保存它。代理引用“信标”以获取实现地址。当需要跨多个代理实例进行更新时,信标代理非常有用。回到我们的 Gnosis Safe 示例,每个用户的 Safe 都是一个代理合约,想象一下需要进行关键更新。
更新每个 Safe(代理)的实现地址将在 gas 方面成本高昂,并且需要与用户(代理的部署者和所有者)进行大量协调才能进行更新。
有了 Beacon 代理,平台的维护者(例如 Gnosis 团队)只需要在“The Beacon”合约中更新实现地址。指向“The Beacon”的所有代理实例也将被更新。这不仅节省了 gas(因为实现地址只需要在一个位置更新),而且显著减少了操作负担,因为用户无需执行单独的升级。
当然,唯一的缺点是该模式对实现地址的控制很集中。Beacon 的所有者代表着一个重要的信任点。为了减轻这种信任并增强安全性,可以实施诸如多重签名钱包和时间锁等机制。
构造函数和初始化函数的区别
构造函数用于初始化合约中的状态。它们在合约部署时执行一次,它们的代码不包含在合约的字节码中。在代理模式中,“代理合约”(保存状态)和“实现合约”(保存逻辑)是分开的。因此,在“实现合约”的构造函数中进行的任何状态初始化只影响“实现合约”的存储,而不影响“代理合约”的存储。
为了解决代理设置中构造函数的限制,使用了初始化器函数。这些函数旨在在“代理合约”的存储中设置初始状态。初始化器被设计为通过委托调用从“代理合约”中执行。这确保了初始化的状态在“代理合约”的存储中,符合“实现”合约的预期逻辑。与构造函数类似,初始化器只被执行一次。这通常是通过一种机制来强制执行的,比如一个布尔标志,以防止重新初始化,这可能会导致安全漏洞。
需要注意的一点是,与构造函数不同,初始化器不会自动处理继承。在幕后,初始化器只是一个普通函数,这意味着如果“实现”的父合约中有构造函数,则它们需要在初始化器中显式调用。这与构造函数不同,构造函数会自动调用父构造函数。
在实现可升级的合约时,必须特别注意初始化器函数。确保它们是安全的,并且只能按预期调用对于维护合约的完整性至关重要。
代理模式 优点 缺点 简单/Delegatecall - 具备升级和授权功能。 - 用户部署代理成本低。 - 存在函数和存储冲突的风险,可能导致歧义或被恶意利用。 透明代理 - 具备升级和授权功能。 - 消除函数冲突的风险。 - 部署代理时的 Gas 成本较高。 - 用户与合约交互的 Gas 成本较高。 - 需要额外部署 ProxyAdmin 合约。 UUPS - 具备升级和授权功能。 - 消除函数冲突的风险。 - 相比透明代理,用户的 Gas 开销更小。 - 无需部署 ProxyAdmin 合约。 - 支持冻结升级功能。 - 可在实现合约中修改升级逻辑。 - 每次部署实现合约时都需要额外 Gas 成本。 - 认证逻辑和业务逻辑的关注点分离度降低。 - 每次升级都可能改变认证逻辑的攻击面,增加安全风险。 - 升级逻辑若被意外移除,将永久失去升级能力。 信标(Beacon) - 在更新信标合约中的实现合约地址时,所有子代理可同步更新。 - 信标合约是所有子合约的单点故障来源。 最小代理 - 最便宜的代理部署方式。 - 可部署多个共享逻辑的合约实例。 - 不可升级。 - 不具备授权功能。 钻石代理 - 支持单个函数的独立修改。 - 适用于任意长度的合约系统。 - 引入基于函数的权限管理。 - 每个函数和每次升级都是新的合约,可能非常复杂。 - 理解和审计困难,容易出现漏洞。 - 概念复杂,难以管理。
ERC-4337
账户抽象,即 ERC-4337,是一种解决当前以太坊钱包用户体验的新方法。账户抽象充当“智能合约钱包”,用户可以在不拥有自己的私钥或无需维护以太币以支付交易费用的情况下与以太坊网络进行交互。它使用替代内存池(也称为 Alt Mempool)设计来接受和解释消息(我们稍后会详细讨论)以促进这些交易。
账户抽象打开了以下大门:
- 多操作:与智能合约的某些交互涉及多个步骤,并需要多个交易。例如,当与 DeFi 协议交互时,用户可能需要批准代币转移,然后存入该代币,然后执行其他操作。每个步骤都需要由 EOA 单独发起,这是一个繁琐且可能成本高昂的过程。ERC-4337 通过引入一种称为“UserOperation”的新交易类型来解决这个问题。UserOperations 允许用户定义应作为单个操作的一部分执行的一系列步骤。然后,这些步骤由 EntryPoint 合约执行,该合约充当用户的代理。不要担心 UserOperation 和 EntryPoint,我们很快就会详细讨论它们。
- 多签名:ERC-4337 允许多签名功能,为不同的用例打开了大门,例如社交恢复(例如,通过你信任的同行恢复账户)、治理安全(例如,未经授权的交易)等。
- 自定义签名方案:允许使用替代签名方案。以太坊目前使用 ECDSA 进行交易签名,尽管它是安全的并且广泛使用,但额外的签名方案为不同的用例打开了大门,可能会提高互操作性和用户体验。
- Gas 成本灵活性:ERC-4337 支持“赞助交易”,即其他人可以支付 gas 费用,从而在交易费用处理方面提供更大的灵活性。
- 可升级性:ERC-4337 标准使用代理合约,使其可以“升级”。这可以允许在不中断生态系统内互操作性的情况下添加新功能和修复错误。