## 无代理合约 由于区块链的不可篡改特性,一个合约上链之后,其代码将被永久性保存,并且不可更改。在这种情况下,如果项目方部署的合约存在漏洞,而资金又存储在合约中,有可能导致资金被盗取。 ## UUPS(ERC1822 通用可升级代理) ERC1822提出了通用可升级代理模式,该模式定义了代理合约的基础架构:  即将合约分为逻辑合约和代理合约,逻辑合约包含要执行的逻辑(不存储数据,只存有逻辑),而代理合约充当入口,用于调用逻辑合约(存储数据)。 此时,交易会直接于代理合约接触,代理合约通过委托调用(借用逻辑合约的代码)执行交易并更改状态(状态保存在代理合约中)。 但是当前的代理合约依然存在一些问题: 1. 选择器冲突:用户与代理合约交互(通过函数调用),由于代理合约中不存储逻辑,因此会触发fallback函数(在fallback内部委托调用逻辑合约)。然而,当代理合约与逻辑合约中存在两个函数选择器相同的函数时,将导致这次函数调用作用于代理合约中。这导致执行错误逻辑。 2. 存储冲突:由于存在委托调用,因此执行的上下文还是在代理合约中。如果逻辑合约的状态变量布局与代理合约不同,将导致存储时冲突。举例来说: 代理合约的状态存储布局: | state_name | slot | |:---------- | -------- | | a | 0x00...0 | | b | 0x00...1 | 逻辑合约的状态存储布局: | state_name | slot | | ---------- | -------- | | c | 0x00...0 | | a | 0x00...1 | | b | 0x00...2 | 可以发现:如果在逻辑合约中修改状态变量a,那么将修改slot为0x00...1的值,但是在代理合约中0x00...1对应的状态变量是b。这就导致错误的状态修改,甚至有可能导致逻辑合约地址被篡改。 3. 用户角色不明确:在当前UUPS模型中,任何用户都可以修改逻辑合约的地址,这意味着任何人都可能直接修改逻辑合约的实现。 ## ERC1967 针对上述ERC1822遗留的问题,ERC1967解决了一部分。首先,ERC1967定义了几个专用的存储槽: ○ bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1):逻辑合约地址槽。 ○ bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1):管理员地址槽。 ○ bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1):信标合约地址槽。 这些存储槽被预先定义,从而防止存储冲突修改这些关键变量的值,因此解决了上述的问题2。 ## TransaprentProxy 透明代理的提出解决了上述的问题1和问题3。 透明代理主要思想为: 1. 权限分离:将升级合约的权限交给管理员,将执行业务逻辑的权限交给普通用户。 2. 逻辑分离:将升级合约的逻辑存储在代理合约中,将业务逻辑存储在逻辑合约中。 因此,在透明代理中有两种角色: 1. 普通用户:只能够调用逻辑合约中的内容。 2. 管理员:只能够调用升级的逻辑,并且升级的逻辑存储在代理合约中。 透明代理的代码模式如下: 1. 代理合约:包含逻辑转发函数、升级函数以及一些查询函数。 2. 逻辑合约:包含业务逻辑。 针对问题1选择器冲突:在透明代理中,规定代理合约中只有逻辑转发函数、升级函数等,因此不存在问题1。 针对问题3角色不明确:透明代理对用户代理进行了明确的分层,因此解决了问题3。 ## BeaconProxy 信标代理用于解决多个代理合约共用逻辑合约时,修改逻辑合约地址的效率低下问题,举例来说:公司中某个部门有 100 名员工,你想给每个人都换一部 iPhone16ProMax。 如果使用传统代理,你只能一个个换。但如果使用 BeaconProxy,信标代理,那么你可以一次性将这个部门的所有员工的手机都更换。 信标代理相当于一个扩展功能,集中管理多个代理合约的逻辑合约。  交易先发给代理合约,而后代理合约在信标代理中查询实现的地址,而后在根据返回的实现地址执行交易。  可以发现,信标代理就是一个实现地址的存储器,所有实现信标代理的合约都需要先从信标合约中拿到实现地址,再执行交易。这也就是为什么信标代理可以一次性更新所有代理的实现地址。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up