Skip to content

Commit

Permalink
Update whw2025.md
Browse files Browse the repository at this point in the history
  • Loading branch information
whw2025 authored Oct 16, 2024
1 parent e93c514 commit 78a6703
Showing 1 changed file with 114 additions and 0 deletions.
114 changes: 114 additions & 0 deletions whw2025.md
Original file line number Diff line number Diff line change
Expand Up @@ -1690,4 +1690,118 @@ ERC20Released:提币事件,当受益人提取释放代币时释放。

###

### 2024.10.16


第四十七节可升级合约

1、可升级合约就是一个可以更改逻辑合约的代理合约。
2、一个简单的可升级合约包含3个合约:代理合约,旧的逻辑合约,和新的逻辑合约。
3、代理合约包含
(1)3个变量:
1)implementation:逻辑合约地址。
2)admin:admin地址。
3)words:字符串,可以通过逻辑合约的函数改变。

(2)3个函数
1)构造函数:初始化admin和逻辑合约地址。
2)fallback():回调函数,将调用委托给逻辑合约。
3)upgrade():升级函数,改变逻辑合约地址,只能由admin调用
4、旧逻辑合约​
这个逻辑合约包含3个状态变量,与保持代理合约一致,防止插槽冲突。它只有一个函数foo(),将代理合约中的words的值改为"old"。
5、新逻辑合约​
这个逻辑合约包含3个状态变量,与保持代理合约一致,防止插槽冲突。它只有一个函数foo(),将代理合约中的words的值改为"new"。


第四十八节透明代理Transparent Proxy

1、存在的问题:管理员可能会因为“函数选择器冲突”,在调用逻辑合约的函数时,误调用代理合约的可升级函数。

两种解决方案:
(1)透明代理:限制管理员的权限,不让他调用任何逻辑合约的函数;
(2)通用可升级代理

2、透明代理的逻辑:
(1)管理员变为工具人,仅能调用代理合约的可升级函数对合约升级,不能通过回调函数调用逻辑合约。
(2)其它用户不能调用可升级函数,但是可以调用逻辑合约的函数。

3、代理合约的fallback()函数限制了管理员地址的调用。代理合约包含:
(1)3个变量:
1)implementation:逻辑合约地址。
2)admin:admin地址。
3)words:字符串,可以通过逻辑合约的函数改变。
(2)3个函数
1)构造函数:初始化admin和逻辑合约地址。
2)fallback():回调函数,将调用委托给逻辑合约,不能由admin调用。
3)upgrade():升级函数,改变逻辑合约地址,只能由admin调用。

4、逻辑合约:包含3个状态变量,与保持代理合约一致,防止插槽冲突;包含一个函数foo(),旧逻辑合约会将words的值改为"old",新的会改为"new"。


第四十九节通用可升级代理

1、UUPS(universal upgradeable proxy standard,通用可升级代理)将升级函数放在逻辑合约中。这样一来,如果有其它函数与升级函数存在“选择器冲突”,编译时就会报错。

2、普通可升级合约,透明代理,和UUPS的不同点:
标准 可升级函数在 是否回“选择器冲突” 缺点
可升级代理 Proxy合约 会 选择器冲突
透明代理 Proxy合约 不会 费gas
UUPS Logic合约 不会 更复杂


3、UUPS的代理合约的升级函数被放在了逻辑合约中。包含:
(1)3个变量:
1)implementation:逻辑合约地址。
2)admin:admin地址。
3)words:字符串,可以通过逻辑合约的函数改变。
(2)2个函数
1)构造函数:初始化admin和逻辑合约地址。
2)fallback():回调函数,将调用委托给逻辑合约。


4、UUPS的逻辑合约与第47讲中的不同是多了个升级函数。UUPS逻辑合约包含3个状态变量,与保持代理合约一致,防止插槽冲突。它包含2个函数:
(1)upgrade():升级函数,将改变逻辑合约地址implementation,只能由admin调用。
(2)foo():旧UUPS逻辑合约会将words的值改为"old",新的会改为"new"。

5、与透明代理不同,UUPS将升级函数放在了逻辑合约中,从而使得"选择器冲突"不能通过编译。相比透明代理,UUPS更省gas,但也更复杂。


第五十节多签钱包

1、多签钱包是一种电子钱包,特点是交易被多个私钥持有者(多签人)授权后才能执行;
2、在以太坊上的多签钱包其实是智能合约,属于合约钱包。
3、多签钱包MultisigWallet合约的逻辑:
(1)设置多签人和门槛(链上):部署多签合约时,我们需要初始化多签人列表和执行门槛(至少n个多签人签名授权后,交易才能执行)。
(2)创建交易(链下):一笔待授权的交易包含以下内容:
1)to:目标合约。
2)value:交易发送的以太坊数量。
3)data:calldata,包含调用函数的选择器和参数。
4)nonce:初始为0,随着多签合约每笔成功执行的交易递增的值,可以防止签名重放攻击。
5)chainid:链id,防止不同链的签名重放攻击。
(3)收集多签签名(链下):将上一步的交易ABI编码并计算哈希,得到交易哈希,然后让多签人签名,并拼接到一起的到打包签名。
(4)调用多签合约的执行函数,验证签名并执行交易(链上)。

4、MultisigWallet合约有2个事件,ExecutionSuccess和ExecutionFailure,分别在交易成功和失败时释放,参数为交易哈希。

5、MultisigWallet合约有5个状态变量:
(1)owners:多签持有人数组
(2)isOwner:address => bool的映射,记录一个地址是否为多签持有人。
(3)ownerCount:多签持有人数量
(4)threshold:多签执行门槛,交易至少有n个多签人签名才能被执行。
(5)nonce:初始为0,随着多签合约每笔成功执行的交易递增的值,可以防止签名重放攻击。

6、MultisigWallet合约有6个函数:

(1)构造函数:调用_setupOwners(),初始化和多签持有人和执行门槛相关的变量。
(2)_setupOwners():在合约部署时被构造函数调用,初始化owners,isOwner,ownerCount,threshold状态变量。传入的参数中,执行门槛需大于等于1且小于等于多签人数;多签地址不能为0地址且不能重复。
(3)execTransaction():在收集足够的多签签名后,验证签名并执行交易。传入的参数为目标地址to,发送的以太坊数额value,数据data,以及打包签名signatures。打包签名就是将收集的多签人对交易哈希的签名,按多签持有人地址从小到大顺序,打包到一个[bytes]数据中。这一步调用了encodeTransactionData()编码交易,调用了checkSignatures()检验签名是否有效、数量是否达到执行门槛。
(4)checkSignatures():检查签名和交易数据的哈希是否对应,数量是否达到门槛,若否,交易会revert。单个签名长度为65字节,因此打包签名的长度要长于threshold * 65。调用了signatureSplit()分离出单个签名。这个函数的大致思路:
1)用ecdsa获取签名地址.
2)利用 currentOwner > lastOwner 确定签名来自不同多签(多签地址递增)。
3)利用isOwner[currentOwner]确定签名者为多签持有人。
(5)signatureSplit():将单个签名从打包的签名分离出来,参数分别为打包签名signatures和要读取的签名位置pos。利用了内联汇编,将签名的r,s,和v三个值分离出来。
(6)encodeTransactionData():将交易数据打包并计算哈希,利用了abi.encode()和keccak256()函数。这个函数可以计算出一个交易的哈希,然后在链下让多签人签名并收集,再调用execTransaction()函数执行。

###

<!-- Content_END -->

0 comments on commit 78a6703

Please sign in to comment.