今天簡單介紹抽象帳戶的偽交易物件 - User Operation 的每個欄位。
2024/2 以太坊官方帳戶抽象開發團隊 eth_infinitism 發佈了 ERC-4337 v0.7,相較於 v0.6 的 User Operation 有 11 個欄位,在 v0.7 版中改為 9 個欄位,struct 的名字換成 PackedUserOperation:
struct PackedUserOperation {
address sender;
uint256 nonce;
bytes initCode;
bytes callData;
bytes32 accountGasLimits;
uint256 preVerificationGas;
bytes32 gasFees;
bytes paymasterAndData;
bytes signature;
}
交易的發起者,即 SCA 的地址。
避免重送攻擊的計數器。
選填,若 SCA 尚未部署,會執行這裡的 code 來部署合約。部署 SCA 和第一筆交易可以合起來成一筆交易。
由 EntryPoint 對 SCA 呼叫的 calldata,即 SCA 要執行的交易內容。
32-bytes 的資料由兩個 gasLimit 組成,一個是驗證一個是執行:
例如:
0x000000000000000000000000000f423f000000000000000000000000000f423f
簡稱 PVG,用於補貼 Bundler 執行 EntryPoint.handleOps 之外所消耗的 gas。如果使用 Bundler 送 UserOps 這欄沒給或給太少,Bundler 可能就不幫你送 UserOps 了。
詳情見 Stackup - An analysis of PreVerificationGas
32-bytes 的資料由 maxPriorityFeePerGas 和 maxFeePerGas 組成。
EIP-1559 的手續費公式:
ActualGasPrice = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
GasFee = GasPrice * GasUsed
選填,如果要使用 paymaster 在這填寫相關資料。
(尚未研究 paymaster 之後補上)
用於 SCA 要驗的簽章,以 SimpleAccount.sol 為例,它的 _validateSignature
如下:
function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)
internal override virtual returns (uint256 validationData) {
bytes32 hash = MessageHashUtils.toEthSignedMessageHash(userOpHash);
if (owner != ECDSA.recover(hash, userOp.signature))
return SIG_VALIDATION_FAILED;
return SIG_VALIDATION_SUCCESS;
}
SimpleAccount 的擁有者製作簽章的方式如下:
bytes32 userOpHash = IEntryPoint(entryPoint).getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(0xbeef, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature = abi.encodePacked(r, s, v);