mirror of
https://github.com/getwax/bls-wallet.git
synced 2026-01-09 15:48:11 -05:00
Compare commits
2 Commits
v1.0.0
...
4337-explo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaa09dc917 | ||
|
|
2e68505b2e |
@@ -57,6 +57,7 @@ export default class BlsWalletWrapper {
|
||||
const initFunctionParams =
|
||||
BLSWallet__factory.createInterface().encodeFunctionData("initialize", [
|
||||
verificationGatewayAddress,
|
||||
ethers.constants.AddressZero, // TODO: 4337 EntryPoint address
|
||||
]);
|
||||
|
||||
return ethers.utils.getCreate2Address(
|
||||
|
||||
@@ -6,7 +6,7 @@ pragma abicoder v2;
|
||||
//To avoid constructor params having forbidden evm bytecodes on Optimism
|
||||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
||||
import "./interfaces/IWallet.sol";
|
||||
|
||||
import "./interfaces/UserOperation4337.sol";
|
||||
|
||||
/** Minimal upgradable smart contract wallet.
|
||||
Generic calls can only be requested by its trusted gateway.
|
||||
@@ -23,6 +23,7 @@ contract BLSWallet is Initializable, IWallet
|
||||
|
||||
// BLS variables
|
||||
address public trustedBLSGateway;
|
||||
address public trustedEntryPoint;
|
||||
address pendingBLSGateway;
|
||||
uint256 pendingGatewayTime;
|
||||
|
||||
@@ -49,10 +50,12 @@ contract BLSWallet is Initializable, IWallet
|
||||
);
|
||||
|
||||
function initialize(
|
||||
address blsGateway
|
||||
address blsGateway,
|
||||
address entryPoint
|
||||
) external initializer {
|
||||
nonce = 0;
|
||||
trustedBLSGateway = blsGateway;
|
||||
trustedEntryPoint = entryPoint;
|
||||
}
|
||||
|
||||
receive() external payable {}
|
||||
@@ -144,7 +147,7 @@ contract BLSWallet is Initializable, IWallet
|
||||
*/
|
||||
function performOperation(
|
||||
IWallet.Operation calldata op
|
||||
) public payable onlyTrustedGateway thisNonce(op.nonce) returns (
|
||||
) public payable onlyTrusted thisNonce(op.nonce) returns (
|
||||
bool success,
|
||||
bytes[] memory results
|
||||
) {
|
||||
@@ -221,6 +224,25 @@ contract BLSWallet is Initializable, IWallet
|
||||
nonce++;
|
||||
}
|
||||
|
||||
// --- <4337> ---
|
||||
|
||||
function validateUserOp(
|
||||
UserOperation4337 calldata userOp,
|
||||
bytes32 requestId,
|
||||
address aggregator,
|
||||
uint256 missingWalletFunds
|
||||
) external view {
|
||||
require(aggregator == trustedBLSGateway);
|
||||
require(userOp.nonce == nonce);
|
||||
require(missingWalletFunds == 0);
|
||||
}
|
||||
|
||||
function getAggregator() public view returns (address) {
|
||||
return trustedBLSGateway;
|
||||
}
|
||||
|
||||
// --- </4337> ---
|
||||
|
||||
modifier onlyThis() {
|
||||
require(msg.sender == address(this), "BLSWallet: only callable from this");
|
||||
_;
|
||||
@@ -234,6 +256,15 @@ contract BLSWallet is Initializable, IWallet
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyTrusted() {
|
||||
require(
|
||||
msg.sender == trustedBLSGateway ||
|
||||
msg.sender == trustedEntryPoint,
|
||||
"BLSWallet: only callable from trusted gateway or 4337 entry point"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier thisNonce(uint256 opNonce) {
|
||||
require(opNonce == nonce, "BLSWallet: only callable with current nonce");
|
||||
_;
|
||||
|
||||
@@ -8,6 +8,7 @@ import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
|
||||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
|
||||
|
||||
import "./interfaces/IWallet.sol";
|
||||
import "./interfaces/UserOperation4337.sol";
|
||||
|
||||
/**
|
||||
A non-upgradable gateway used to create BLSWallets and call them with
|
||||
@@ -26,7 +27,7 @@ contract VerificationGateway
|
||||
ProxyAdmin public immutable walletProxyAdmin;
|
||||
address public immutable blsWalletLogic;
|
||||
mapping(bytes32 => IWallet) public walletFromHash;
|
||||
mapping(IWallet => bytes32) public hashFromWallet;
|
||||
mapping(IWallet => uint256[BLS_KEY_LEN]) public blsKeyFromWallet;
|
||||
|
||||
//mapping from an existing wallet's bls key hash to pending variables when setting a new BLS key
|
||||
mapping(bytes32 => uint256[BLS_KEY_LEN]) public pendingBLSPublicKeyFromHash;
|
||||
@@ -100,148 +101,158 @@ contract VerificationGateway
|
||||
require(verified, "VG: Sig not verified");
|
||||
}
|
||||
|
||||
/**
|
||||
If an existing wallet contract wishes to be called by this verification
|
||||
gateway, it can directly register itself with a simple signed msg.
|
||||
NB: this is independent of the proxyAdmin, and if desired can be changed
|
||||
via the corresponding call.
|
||||
@dev overrides previous wallet address registered with the given public key
|
||||
@param messageSenderSignature signature of message containing only the calling address
|
||||
@param publicKey that signed the caller's address
|
||||
*/
|
||||
function setBLSKeyForWallet(
|
||||
uint256[2] memory messageSenderSignature,
|
||||
uint256[BLS_KEY_LEN] memory publicKey
|
||||
) public {
|
||||
require(blsLib.isZeroBLSKey(publicKey) == false, "VG: publicKey must be non-zero");
|
||||
IWallet wallet = IWallet(msg.sender);
|
||||
bytes32 existingHash = hashFromWallet[wallet];
|
||||
if (existingHash == bytes32(0)) { // wallet does not yet have a bls key registered with this gateway
|
||||
// set it instantly
|
||||
safeSetWallet(messageSenderSignature, publicKey, wallet);
|
||||
}
|
||||
else { // wallet already has a key registered, set after delay
|
||||
pendingMessageSenderSignatureFromHash[existingHash] = messageSenderSignature;
|
||||
pendingBLSPublicKeyFromHash[existingHash] = publicKey;
|
||||
pendingBLSPublicKeyTimeFromHash[existingHash] = block.timestamp + 604800; // 1 week from now
|
||||
emit PendingBLSKeySet(existingHash, publicKey);
|
||||
function hashFromWallet(IWallet wallet) public view returns (bytes32) {
|
||||
uint256[BLS_KEY_LEN] memory blsKey = blsKeyFromWallet[wallet];
|
||||
|
||||
if (blsLib.isZeroBLSKey(blsKey)) {
|
||||
return bytes32(0);
|
||||
}
|
||||
|
||||
return keccak256(abi.encodePacked(blsKey));
|
||||
}
|
||||
|
||||
function setPendingBLSKeyForWallet() public {
|
||||
IWallet wallet = IWallet(msg.sender);
|
||||
bytes32 existingHash = hashFromWallet[wallet];
|
||||
require(existingHash != bytes32(0), "VG: hash does not exist for caller");
|
||||
if (
|
||||
(pendingBLSPublicKeyTimeFromHash[existingHash] != 0) &&
|
||||
(block.timestamp > pendingBLSPublicKeyTimeFromHash[existingHash])
|
||||
) {
|
||||
safeSetWallet(
|
||||
pendingMessageSenderSignatureFromHash[existingHash],
|
||||
pendingBLSPublicKeyFromHash[existingHash],
|
||||
wallet
|
||||
);
|
||||
pendingMessageSenderSignatureFromHash[existingHash] = [0,0];
|
||||
pendingBLSPublicKeyTimeFromHash[existingHash] = 0;
|
||||
pendingBLSPublicKeyFromHash[existingHash] = [0,0,0,0];
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// If an existing wallet contract wishes to be called by this verification
|
||||
// gateway, it can directly register itself with a simple signed msg.
|
||||
// NB: this is independent of the proxyAdmin, and if desired can be changed
|
||||
// via the corresponding call.
|
||||
// @dev overrides previous wallet address registered with the given public key
|
||||
// @param messageSenderSignature signature of message containing only the calling address
|
||||
// @param publicKey that signed the caller's address
|
||||
// */
|
||||
// function setBLSKeyForWallet(
|
||||
// uint256[2] memory messageSenderSignature,
|
||||
// uint256[BLS_KEY_LEN] memory publicKey
|
||||
// ) public {
|
||||
// require(blsLib.isZeroBLSKey(publicKey) == false, "VG: publicKey must be non-zero");
|
||||
// IWallet wallet = IWallet(msg.sender);
|
||||
// bytes32 existingHash = hashFromWallet(wallet);
|
||||
// if (existingHash == bytes32(0)) { // wallet does not yet have a bls key registered with this gateway
|
||||
// // set it instantly
|
||||
// safeSetWallet(messageSenderSignature, publicKey, wallet);
|
||||
// }
|
||||
// else { // wallet already has a key registered, set after delay
|
||||
// pendingMessageSenderSignatureFromHash[existingHash] = messageSenderSignature;
|
||||
// pendingBLSPublicKeyFromHash[existingHash] = publicKey;
|
||||
// pendingBLSPublicKeyTimeFromHash[existingHash] = block.timestamp + 604800; // 1 week from now
|
||||
// emit PendingBLSKeySet(existingHash, publicKey);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
Calls to proxy admin, exclusively from a wallet. Must be called twice.
|
||||
Once to set the function in the wallet as pending, then again after the recovery time.
|
||||
@param hash calling wallet's bls public key hash
|
||||
@param encodedFunction the selector and params to call (first encoded param must be calling wallet)
|
||||
*/
|
||||
function walletAdminCall(
|
||||
bytes32 hash,
|
||||
bytes memory encodedFunction
|
||||
) public onlyWallet(hash) {
|
||||
IWallet wallet = walletFromHash[hash];
|
||||
// function setPendingBLSKeyForWallet() public {
|
||||
// IWallet wallet = IWallet(msg.sender);
|
||||
// bytes32 existingHash = hashFromWallet(wallet);
|
||||
// require(existingHash != bytes32(0), "VG: hash does not exist for caller");
|
||||
// if (
|
||||
// (pendingBLSPublicKeyTimeFromHash[existingHash] != 0) &&
|
||||
// (block.timestamp > pendingBLSPublicKeyTimeFromHash[existingHash])
|
||||
// ) {
|
||||
// safeSetWallet(
|
||||
// pendingMessageSenderSignatureFromHash[existingHash],
|
||||
// pendingBLSPublicKeyFromHash[existingHash],
|
||||
// wallet
|
||||
// );
|
||||
// pendingMessageSenderSignatureFromHash[existingHash] = [0,0];
|
||||
// pendingBLSPublicKeyTimeFromHash[existingHash] = 0;
|
||||
// pendingBLSPublicKeyFromHash[existingHash] = [0,0,0,0];
|
||||
// }
|
||||
// }
|
||||
|
||||
// ensure first parameter is the calling wallet address
|
||||
bytes memory encodedAddress = abi.encode(address(wallet));
|
||||
uint8 selectorOffset = 4;
|
||||
for (uint256 i=0; i<32; i++) {
|
||||
require(
|
||||
(encodedFunction[selectorOffset+i] == encodedAddress[i]),
|
||||
"VG: first param to proxy admin is not calling wallet"
|
||||
);
|
||||
}
|
||||
// /**
|
||||
// Calls to proxy admin, exclusively from a wallet. Must be called twice.
|
||||
// Once to set the function in the wallet as pending, then again after the recovery time.
|
||||
// @param hash calling wallet's bls public key hash
|
||||
// @param encodedFunction the selector and params to call (first encoded param must be calling wallet)
|
||||
// */
|
||||
// function walletAdminCall(
|
||||
// bytes32 hash,
|
||||
// bytes memory encodedFunction
|
||||
// ) public onlyWallet(hash) {
|
||||
// IWallet wallet = walletFromHash[hash];
|
||||
|
||||
wallet.setAnyPending();
|
||||
// // ensure first parameter is the calling wallet address
|
||||
// bytes memory encodedAddress = abi.encode(address(wallet));
|
||||
// uint8 selectorOffset = 4;
|
||||
// for (uint256 i=0; i<32; i++) {
|
||||
// require(
|
||||
// (encodedFunction[selectorOffset+i] == encodedAddress[i]),
|
||||
// "VG: first param to proxy admin is not calling wallet"
|
||||
// );
|
||||
// }
|
||||
|
||||
// ensure wallet has pre-approved encodedFunction
|
||||
bytes32 approvedFunctionHash = wallet.approvedProxyAdminFunctionHash();
|
||||
bytes32 encodedFunctionHash = keccak256(encodedFunction);
|
||||
bool matchesApproved = encodedFunctionHash == approvedFunctionHash;
|
||||
// wallet.setAnyPending();
|
||||
|
||||
if (matchesApproved == false) {
|
||||
// prepare for a future call
|
||||
wallet.setProxyAdminFunctionHash(encodedFunctionHash);
|
||||
}
|
||||
else {
|
||||
// call approved function
|
||||
(bool success, ) = address(walletProxyAdmin).call(encodedFunction);
|
||||
require(success, "VG: call to proxy admin failed");
|
||||
wallet.clearApprovedProxyAdminFunctionHash();
|
||||
}
|
||||
}
|
||||
// // ensure wallet has pre-approved encodedFunction
|
||||
// bytes32 approvedFunctionHash = wallet.approvedProxyAdminFunctionHash();
|
||||
// bytes32 encodedFunctionHash = keccak256(encodedFunction);
|
||||
// bool matchesApproved = encodedFunctionHash == approvedFunctionHash;
|
||||
|
||||
/**
|
||||
Recovers a wallet, setting a new bls public key.
|
||||
@param walletAddressSignature signature of message containing only the wallet address
|
||||
@param blsKeyHash calling wallet's bls public key hash
|
||||
@param salt used in the recovery hash
|
||||
@param newBLSKey to set as the wallet's bls public key
|
||||
*/
|
||||
function recoverWallet(
|
||||
uint256[2] memory walletAddressSignature,
|
||||
bytes32 blsKeyHash,
|
||||
bytes32 salt,
|
||||
uint256[BLS_KEY_LEN] memory newBLSKey
|
||||
) public {
|
||||
IWallet wallet = walletFromHash[blsKeyHash];
|
||||
bytes32 recoveryHash = keccak256(
|
||||
abi.encodePacked(msg.sender, blsKeyHash, salt)
|
||||
);
|
||||
if (recoveryHash == wallet.recoveryHash()) {
|
||||
safeSetWallet(walletAddressSignature, newBLSKey, wallet);
|
||||
wallet.recover();
|
||||
}
|
||||
}
|
||||
// if (matchesApproved == false) {
|
||||
// // prepare for a future call
|
||||
// wallet.setProxyAdminFunctionHash(encodedFunctionHash);
|
||||
// }
|
||||
// else {
|
||||
// // call approved function
|
||||
// (bool success, ) = address(walletProxyAdmin).call(encodedFunction);
|
||||
// require(success, "VG: call to proxy admin failed");
|
||||
// wallet.clearApprovedProxyAdminFunctionHash();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
Wallet can migrate to a new gateway, eg additional signature support
|
||||
*/
|
||||
function setTrustedBLSGateway(
|
||||
bytes32 hash,
|
||||
address blsGateway
|
||||
) public onlyWallet(hash) {
|
||||
uint256 size;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly { size := extcodesize(blsGateway) }
|
||||
require(
|
||||
(blsGateway != address(0)) && (size > 0),
|
||||
"BLSWallet: gateway address param not valid"
|
||||
);
|
||||
// /**
|
||||
// Recovers a wallet, setting a new bls public key.
|
||||
// @param walletAddressSignature signature of message containing only the wallet address
|
||||
// @param blsKeyHash calling wallet's bls public key hash
|
||||
// @param salt used in the recovery hash
|
||||
// @param newBLSKey to set as the wallet's bls public key
|
||||
// */
|
||||
// function recoverWallet(
|
||||
// uint256[2] memory walletAddressSignature,
|
||||
// bytes32 blsKeyHash,
|
||||
// bytes32 salt,
|
||||
// uint256[BLS_KEY_LEN] memory newBLSKey
|
||||
// ) public {
|
||||
// IWallet wallet = walletFromHash[blsKeyHash];
|
||||
// bytes32 recoveryHash = keccak256(
|
||||
// abi.encodePacked(msg.sender, blsKeyHash, salt)
|
||||
// );
|
||||
// if (recoveryHash == wallet.recoveryHash()) {
|
||||
// safeSetWallet(walletAddressSignature, newBLSKey, wallet);
|
||||
// wallet.recover();
|
||||
// }
|
||||
// }
|
||||
|
||||
IWallet wallet = walletFromHash[hash];
|
||||
// /**
|
||||
// Wallet can migrate to a new gateway, eg additional signature support
|
||||
// */
|
||||
// function setTrustedBLSGateway(
|
||||
// bytes32 hash,
|
||||
// address blsGateway
|
||||
// ) public onlyWallet(hash) {
|
||||
// uint256 size;
|
||||
// // solhint-disable-next-line no-inline-assembly
|
||||
// assembly { size := extcodesize(blsGateway) }
|
||||
// require(
|
||||
// (blsGateway != address(0)) && (size > 0),
|
||||
// "BLSWallet: gateway address param not valid"
|
||||
// );
|
||||
|
||||
require(
|
||||
VerificationGateway(blsGateway).walletFromHash(hash) == wallet,
|
||||
"Not recognized"
|
||||
);
|
||||
// IWallet wallet = walletFromHash[hash];
|
||||
|
||||
// getProxyAdmin fails if not called by the current proxy admin, so this
|
||||
// enforces that the wallet's proxy admin matches the one in the new
|
||||
// gateway.
|
||||
VerificationGateway(blsGateway).walletProxyAdmin().getProxyAdmin(
|
||||
TransparentUpgradeableProxy(payable(address(wallet)))
|
||||
);
|
||||
// require(
|
||||
// VerificationGateway(blsGateway).walletFromHash(hash) == wallet,
|
||||
// "Not recognized"
|
||||
// );
|
||||
|
||||
wallet.setTrustedGateway(blsGateway);
|
||||
}
|
||||
// // getProxyAdmin fails if not called by the current proxy admin, so this
|
||||
// // enforces that the wallet's proxy admin matches the one in the new
|
||||
// // gateway.
|
||||
// VerificationGateway(blsGateway).walletProxyAdmin().getProxyAdmin(
|
||||
// TransparentUpgradeableProxy(payable(address(wallet)))
|
||||
// );
|
||||
|
||||
// wallet.setTrustedGateway(blsGateway);
|
||||
// }
|
||||
|
||||
/**
|
||||
Base function for verifying and processing BLS-signed transactions.
|
||||
@@ -299,7 +310,7 @@ contract VerificationGateway
|
||||
address(walletProxyAdmin),
|
||||
getInitializeData()
|
||||
)));
|
||||
updateWalletHashMappings(publicKeyHash, blsWallet);
|
||||
updateWalletHashMappings(publicKey, blsWallet);
|
||||
emit WalletCreated(
|
||||
address(blsWallet),
|
||||
publicKey
|
||||
@@ -328,29 +339,30 @@ contract VerificationGateway
|
||||
blsLib.verifySingle(wallletAddressSignature, publicKey, addressMsg),
|
||||
"VG: Signature not verified for wallet address."
|
||||
);
|
||||
bytes32 publicKeyHash = keccak256(abi.encodePacked(
|
||||
publicKey
|
||||
));
|
||||
emit BLSKeySetForWallet(publicKey, wallet);
|
||||
updateWalletHashMappings(publicKeyHash, wallet);
|
||||
updateWalletHashMappings(publicKey, wallet);
|
||||
}
|
||||
|
||||
/** @dev Only to be called on wallet creation, and in `safeSetWallet` */
|
||||
function updateWalletHashMappings(
|
||||
bytes32 publicKeyHash,
|
||||
uint256[BLS_KEY_LEN] memory blsKey,
|
||||
IWallet wallet
|
||||
) private {
|
||||
// remove reference from old hash
|
||||
bytes32 oldHash = hashFromWallet[wallet];
|
||||
bytes32 oldHash = hashFromWallet(wallet);
|
||||
walletFromHash[oldHash] = IWallet(address(0));
|
||||
|
||||
// update new hash / wallet mappings
|
||||
walletFromHash[publicKeyHash] = wallet;
|
||||
hashFromWallet[wallet] = publicKeyHash;
|
||||
walletFromHash[keccak256(abi.encodePacked(blsKey))] = wallet;
|
||||
blsKeyFromWallet[wallet] = blsKey;
|
||||
}
|
||||
|
||||
function getInitializeData() private view returns (bytes memory) {
|
||||
return abi.encodeWithSignature("initialize(address)", address(this));
|
||||
return abi.encodeWithSignature(
|
||||
"initialize(address,address)",
|
||||
address(this),
|
||||
address(0) // TODO: 4337 EntryPoint address
|
||||
);
|
||||
}
|
||||
|
||||
modifier onlyWallet(bytes32 hash) {
|
||||
@@ -387,4 +399,49 @@ contract VerificationGateway
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
// --- <4337> ---
|
||||
|
||||
// These functions seem to exist to allow clients (aka nodes) to rely on logic defined on-chain
|
||||
// so that they don't need to implement anything specific to any signature aggregation scheme.
|
||||
// For our prototype we can do this specific implementation and make this work without these
|
||||
// functions. Later, it might be necessary to add these for compatibility with clients relying
|
||||
// on this generic technique.
|
||||
// function validateUserOpSignature(
|
||||
// UserOperation4337 calldata userOp,
|
||||
// bool offChainSigCheck
|
||||
// ) external view returns (
|
||||
// bytes memory sigForUserOp,
|
||||
// bytes memory sigForAggregation,
|
||||
// bytes memory offChainSigInfo
|
||||
// ) {}
|
||||
// function aggregateSignatures(
|
||||
// bytes[] calldata sigsForAggregation
|
||||
// ) external view returns (bytes memory aggregatesSignature) {}
|
||||
|
||||
function validateSignatures(
|
||||
UserOperation4337[] calldata userOps,
|
||||
bytes calldata signature
|
||||
) view external {
|
||||
uint256[2][] memory messages = new uint256[2][](userOps.length);
|
||||
uint256[BLS_KEY_LEN][] memory senderPublicKeys = new uint256[BLS_KEY_LEN][](userOps.length);
|
||||
|
||||
for (uint256 i = 0; i < userOps.length; i++) {
|
||||
messages[i] = blsLib.hashToPoint(
|
||||
BLS_DOMAIN,
|
||||
abi.encode(userOps[i])
|
||||
);
|
||||
|
||||
senderPublicKeys[i] = blsKeyFromWallet[IWallet(userOps[i].sender)];
|
||||
}
|
||||
|
||||
bool verified = blsLib.verifyMultiple(
|
||||
abi.decode(signature, (uint256[2])),
|
||||
senderPublicKeys,
|
||||
messages
|
||||
);
|
||||
|
||||
require(verified, "VG: Sig not verified");
|
||||
}
|
||||
|
||||
// --- </4337> ---
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ interface IWallet {
|
||||
bytes encodedFunction;
|
||||
}
|
||||
|
||||
function initialize(address gateway) external;
|
||||
function initialize(address gateway, address entryPoint) external;
|
||||
function nonce() external returns (uint256);
|
||||
|
||||
function performOperation(
|
||||
|
||||
16
contracts/contracts/interfaces/UserOperation4337.sol
Normal file
16
contracts/contracts/interfaces/UserOperation4337.sol
Normal file
@@ -0,0 +1,16 @@
|
||||
//SPDX-License-Identifier: Unlicense
|
||||
pragma solidity >=0.8.4 <0.9.0;
|
||||
|
||||
struct UserOperation4337 {
|
||||
address sender;
|
||||
uint256 nonce;
|
||||
bytes initCode;
|
||||
bytes callData;
|
||||
uint256 callGasLimit;
|
||||
uint256 verificationGasLimit;
|
||||
uint256 preVerificationGas;
|
||||
uint256 maxFeePerGas;
|
||||
uint256 maxPriorityFeePerGas;
|
||||
bytes paymasterAndData;
|
||||
bytes signature;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ const config: HardhatUserConfig = {
|
||||
hardhat: {
|
||||
initialBaseFeePerGas: 0, // workaround from https://github.com/sc-forks/solidity-coverage/issues/652#issuecomment-896330136 . Remove when that issue is closed.
|
||||
accounts,
|
||||
blockGasLimit: 30_000_000,
|
||||
blockGasLimit: 200_000_000,
|
||||
},
|
||||
gethDev: {
|
||||
url: `http://localhost:8545`,
|
||||
|
||||
@@ -1,251 +1,251 @@
|
||||
import { expect } from "chai";
|
||||
import { BigNumber } from "ethers";
|
||||
import { solidityPack } from "ethers/lib/utils";
|
||||
import { ethers, network } from "hardhat";
|
||||
// import { expect } from "chai";
|
||||
// import { BigNumber } from "ethers";
|
||||
// import { solidityPack } from "ethers/lib/utils";
|
||||
// import { ethers, network } from "hardhat";
|
||||
|
||||
import { BlsWalletWrapper, Signature } from "../clients/src";
|
||||
import Fixture from "../shared/helpers/Fixture";
|
||||
import deployAndRunPrecompileCostEstimator from "../shared/helpers/deployAndRunPrecompileCostEstimator";
|
||||
import { defaultDeployerAddress } from "../shared/helpers/deployDeployer";
|
||||
import { BLSWallet, VerificationGateway } from "../typechain";
|
||||
// import { BlsWalletWrapper, Signature } from "../clients/src";
|
||||
// import Fixture from "../shared/helpers/Fixture";
|
||||
// import deployAndRunPrecompileCostEstimator from "../shared/helpers/deployAndRunPrecompileCostEstimator";
|
||||
// import { defaultDeployerAddress } from "../shared/helpers/deployDeployer";
|
||||
// import { BLSWallet, VerificationGateway } from "../typechain";
|
||||
|
||||
const signWalletAddress = async (
|
||||
fx: Fixture,
|
||||
senderAddr: string,
|
||||
signerPrivKey: string,
|
||||
): Promise<Signature> => {
|
||||
const addressMessage = solidityPack(["address"], [senderAddr]);
|
||||
const wallet = await BlsWalletWrapper.connect(
|
||||
signerPrivKey,
|
||||
fx.verificationGateway.address,
|
||||
fx.provider,
|
||||
);
|
||||
return wallet.signMessage(addressMessage);
|
||||
};
|
||||
// const signWalletAddress = async (
|
||||
// fx: Fixture,
|
||||
// senderAddr: string,
|
||||
// signerPrivKey: string,
|
||||
// ): Promise<Signature> => {
|
||||
// const addressMessage = solidityPack(["address"], [senderAddr]);
|
||||
// const wallet = await BlsWalletWrapper.connect(
|
||||
// signerPrivKey,
|
||||
// fx.verificationGateway.address,
|
||||
// fx.provider,
|
||||
// );
|
||||
// return wallet.signMessage(addressMessage);
|
||||
// };
|
||||
|
||||
describe("Recovery", async function () {
|
||||
this.beforeAll(async function () {
|
||||
// deploy the deployer contract for the transient hardhat network
|
||||
if (network.name === "hardhat") {
|
||||
// fund deployer wallet address
|
||||
const fundedSigner = (await ethers.getSigners())[0];
|
||||
await (
|
||||
await fundedSigner.sendTransaction({
|
||||
to: defaultDeployerAddress(),
|
||||
value: ethers.utils.parseEther("1"),
|
||||
})
|
||||
).wait();
|
||||
// describe("Recovery", async function () {
|
||||
// this.beforeAll(async function () {
|
||||
// // deploy the deployer contract for the transient hardhat network
|
||||
// if (network.name === "hardhat") {
|
||||
// // fund deployer wallet address
|
||||
// const fundedSigner = (await ethers.getSigners())[0];
|
||||
// await (
|
||||
// await fundedSigner.sendTransaction({
|
||||
// to: defaultDeployerAddress(),
|
||||
// value: ethers.utils.parseEther("1"),
|
||||
// })
|
||||
// ).wait();
|
||||
|
||||
// deploy the precompile contract (via deployer)
|
||||
console.log("PCE:", await deployAndRunPrecompileCostEstimator());
|
||||
}
|
||||
});
|
||||
// // deploy the precompile contract (via deployer)
|
||||
// console.log("PCE:", await deployAndRunPrecompileCostEstimator());
|
||||
// }
|
||||
// });
|
||||
|
||||
const safetyDelaySeconds = 7 * 24 * 60 * 60;
|
||||
let fx: Fixture;
|
||||
let vg: VerificationGateway;
|
||||
let wallet1: BlsWalletWrapper;
|
||||
let wallet2: BlsWalletWrapper;
|
||||
let walletAttacker: BlsWalletWrapper;
|
||||
let blsWallet: BLSWallet;
|
||||
let recoverySigner;
|
||||
let hash1, hash2, hashAttacker;
|
||||
let salt;
|
||||
let recoveryHash;
|
||||
beforeEach(async function () {
|
||||
fx = await Fixture.create();
|
||||
vg = fx.verificationGateway;
|
||||
// const safetyDelaySeconds = 7 * 24 * 60 * 60;
|
||||
// let fx: Fixture;
|
||||
// let vg: VerificationGateway;
|
||||
// let wallet1: BlsWalletWrapper;
|
||||
// let wallet2: BlsWalletWrapper;
|
||||
// let walletAttacker: BlsWalletWrapper;
|
||||
// let blsWallet: BLSWallet;
|
||||
// let recoverySigner;
|
||||
// let hash1, hash2, hashAttacker;
|
||||
// let salt;
|
||||
// let recoveryHash;
|
||||
// beforeEach(async function () {
|
||||
// fx = await Fixture.create();
|
||||
// vg = fx.verificationGateway;
|
||||
|
||||
wallet1 = await fx.lazyBlsWallets[0]();
|
||||
wallet2 = await fx.lazyBlsWallets[1]();
|
||||
walletAttacker = await fx.lazyBlsWallets[2]();
|
||||
blsWallet = await ethers.getContractAt("BLSWallet", wallet1.address);
|
||||
recoverySigner = (await ethers.getSigners())[1];
|
||||
// wallet1 = await fx.lazyBlsWallets[0]();
|
||||
// wallet2 = await fx.lazyBlsWallets[1]();
|
||||
// walletAttacker = await fx.lazyBlsWallets[2]();
|
||||
// blsWallet = await ethers.getContractAt("BLSWallet", wallet1.address);
|
||||
// recoverySigner = (await ethers.getSigners())[1];
|
||||
|
||||
hash1 = wallet1.blsWalletSigner.getPublicKeyHash(wallet1.privateKey);
|
||||
hash2 = wallet2.blsWalletSigner.getPublicKeyHash(wallet2.privateKey);
|
||||
hashAttacker = wallet2.blsWalletSigner.getPublicKeyHash(
|
||||
walletAttacker.privateKey,
|
||||
);
|
||||
salt = "0x1234567812345678123456781234567812345678123456781234567812345678";
|
||||
recoveryHash = ethers.utils.solidityKeccak256(
|
||||
["address", "bytes32", "bytes32"],
|
||||
[recoverySigner.address, hash1, salt],
|
||||
);
|
||||
});
|
||||
// hash1 = wallet1.blsWalletSigner.getPublicKeyHash(wallet1.privateKey);
|
||||
// hash2 = wallet2.blsWalletSigner.getPublicKeyHash(wallet2.privateKey);
|
||||
// hashAttacker = wallet2.blsWalletSigner.getPublicKeyHash(
|
||||
// walletAttacker.privateKey,
|
||||
// );
|
||||
// salt = "0x1234567812345678123456781234567812345678123456781234567812345678";
|
||||
// recoveryHash = ethers.utils.solidityKeccak256(
|
||||
// ["address", "bytes32", "bytes32"],
|
||||
// [recoverySigner.address, hash1, salt],
|
||||
// );
|
||||
// });
|
||||
|
||||
it("should update bls key", async function () {
|
||||
expect(await vg.hashFromWallet(wallet1.address)).to.eql(hash1);
|
||||
// it("should update bls key", async function () {
|
||||
// expect(await vg.hashFromWallet(wallet1.address)).to.eql(hash1);
|
||||
|
||||
const addressSignature = await signWalletAddress(
|
||||
fx,
|
||||
wallet1.address,
|
||||
wallet2.privateKey,
|
||||
);
|
||||
// const addressSignature = await signWalletAddress(
|
||||
// fx,
|
||||
// wallet1.address,
|
||||
// wallet2.privateKey,
|
||||
// );
|
||||
|
||||
await fx.call(
|
||||
wallet1,
|
||||
vg,
|
||||
"setBLSKeyForWallet",
|
||||
[addressSignature, wallet2.PublicKey()],
|
||||
1,
|
||||
);
|
||||
// await fx.call(
|
||||
// wallet1,
|
||||
// vg,
|
||||
// "setBLSKeyForWallet",
|
||||
// [addressSignature, wallet2.PublicKey()],
|
||||
// 1,
|
||||
// );
|
||||
|
||||
await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
await fx.call(wallet1, vg, "setPendingBLSKeyForWallet", [], 2);
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// await fx.call(wallet1, vg, "setPendingBLSKeyForWallet", [], 2);
|
||||
|
||||
expect(await vg.hashFromWallet(wallet1.address)).to.eql(hash2);
|
||||
});
|
||||
// expect(await vg.hashFromWallet(wallet1.address)).to.eql(hash2);
|
||||
// });
|
||||
|
||||
it("should NOT override public key hash after creation", async function () {
|
||||
let walletForHash = await vg.walletFromHash(hash1);
|
||||
expect(BigNumber.from(walletForHash)).to.not.equal(BigNumber.from(0));
|
||||
expect(walletForHash).to.equal(wallet1.address);
|
||||
// it("should NOT override public key hash after creation", async function () {
|
||||
// let walletForHash = await vg.walletFromHash(hash1);
|
||||
// expect(BigNumber.from(walletForHash)).to.not.equal(BigNumber.from(0));
|
||||
// expect(walletForHash).to.equal(wallet1.address);
|
||||
|
||||
let hashFromWallet = await vg.hashFromWallet(wallet1.address);
|
||||
expect(BigNumber.from(hashFromWallet)).to.not.equal(BigNumber.from(0));
|
||||
expect(hashFromWallet).to.equal(hash1);
|
||||
// let hashFromWallet = await vg.hashFromWallet(wallet1.address);
|
||||
// expect(BigNumber.from(hashFromWallet)).to.not.equal(BigNumber.from(0));
|
||||
// expect(hashFromWallet).to.equal(hash1);
|
||||
|
||||
await fx.call(wallet1, vg, "setPendingBLSKeyForWallet", [], 1);
|
||||
// await fx.call(wallet1, vg, "setPendingBLSKeyForWallet", [], 1);
|
||||
|
||||
walletForHash = await vg.walletFromHash(hash1);
|
||||
expect(walletForHash).to.equal(wallet1.address);
|
||||
// walletForHash = await vg.walletFromHash(hash1);
|
||||
// expect(walletForHash).to.equal(wallet1.address);
|
||||
|
||||
hashFromWallet = await vg.hashFromWallet(wallet1.address);
|
||||
expect(hashFromWallet).to.equal(hash1);
|
||||
});
|
||||
// hashFromWallet = await vg.hashFromWallet(wallet1.address);
|
||||
// expect(hashFromWallet).to.equal(hash1);
|
||||
// });
|
||||
|
||||
it("should set recovery hash", async function () {
|
||||
// set instantly from 0 value
|
||||
await fx.call(wallet1, blsWallet, "setRecoveryHash", [recoveryHash], 1);
|
||||
expect(await blsWallet.recoveryHash()).to.equal(recoveryHash);
|
||||
// it("should set recovery hash", async function () {
|
||||
// // set instantly from 0 value
|
||||
// await fx.call(wallet1, blsWallet, "setRecoveryHash", [recoveryHash], 1);
|
||||
// expect(await blsWallet.recoveryHash()).to.equal(recoveryHash);
|
||||
|
||||
// new value set after delay from non-zero value
|
||||
salt = "0x" + "AB".repeat(32);
|
||||
const newRecoveryHash = ethers.utils.solidityKeccak256(
|
||||
["address", "bytes32", "bytes32"],
|
||||
[recoverySigner.address, hash1, salt],
|
||||
);
|
||||
await fx.call(wallet1, blsWallet, "setRecoveryHash", [newRecoveryHash], 2);
|
||||
expect(await blsWallet.recoveryHash()).to.equal(recoveryHash);
|
||||
await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
await (await blsWallet.setAnyPending()).wait();
|
||||
expect(await blsWallet.recoveryHash()).to.equal(newRecoveryHash);
|
||||
});
|
||||
// // new value set after delay from non-zero value
|
||||
// salt = "0x" + "AB".repeat(32);
|
||||
// const newRecoveryHash = ethers.utils.solidityKeccak256(
|
||||
// ["address", "bytes32", "bytes32"],
|
||||
// [recoverySigner.address, hash1, salt],
|
||||
// );
|
||||
// await fx.call(wallet1, blsWallet, "setRecoveryHash", [newRecoveryHash], 2);
|
||||
// expect(await blsWallet.recoveryHash()).to.equal(recoveryHash);
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// await (await blsWallet.setAnyPending()).wait();
|
||||
// expect(await blsWallet.recoveryHash()).to.equal(newRecoveryHash);
|
||||
// });
|
||||
|
||||
it("should recover before bls key update", async function () {
|
||||
await fx.call(wallet1, blsWallet, "setRecoveryHash", [recoveryHash], 1);
|
||||
// it("should recover before bls key update", async function () {
|
||||
// await fx.call(wallet1, blsWallet, "setRecoveryHash", [recoveryHash], 1);
|
||||
|
||||
const attackSignature = await signWalletAddress(
|
||||
fx,
|
||||
wallet1.address,
|
||||
walletAttacker.privateKey,
|
||||
);
|
||||
// const attackSignature = await signWalletAddress(
|
||||
// fx,
|
||||
// wallet1.address,
|
||||
// walletAttacker.privateKey,
|
||||
// );
|
||||
|
||||
// Attacker assumed to have compromised wallet1 bls key, and wishes to reset
|
||||
// the gateway wallet's bls key to their own.
|
||||
await fx.call(
|
||||
wallet1,
|
||||
vg,
|
||||
"setBLSKeyForWallet",
|
||||
[attackSignature, walletAttacker.PublicKey()],
|
||||
1,
|
||||
);
|
||||
// // Attacker assumed to have compromised wallet1 bls key, and wishes to reset
|
||||
// // the gateway wallet's bls key to their own.
|
||||
// await fx.call(
|
||||
// wallet1,
|
||||
// vg,
|
||||
// "setBLSKeyForWallet",
|
||||
// [attackSignature, walletAttacker.PublicKey()],
|
||||
// 1,
|
||||
// );
|
||||
|
||||
await fx.advanceTimeBy(safetyDelaySeconds / 2); // wait half the time
|
||||
await fx.call(wallet1, vg, "setPendingBLSKeyForWallet", [], 2);
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds / 2); // wait half the time
|
||||
// await fx.call(wallet1, vg, "setPendingBLSKeyForWallet", [], 2);
|
||||
|
||||
const addressSignature = await signWalletAddress(
|
||||
fx,
|
||||
wallet1.address,
|
||||
wallet2.privateKey,
|
||||
);
|
||||
const safeKey = wallet2.PublicKey();
|
||||
// const addressSignature = await signWalletAddress(
|
||||
// fx,
|
||||
// wallet1.address,
|
||||
// wallet2.privateKey,
|
||||
// );
|
||||
// const safeKey = wallet2.PublicKey();
|
||||
|
||||
await (
|
||||
await fx.verificationGateway
|
||||
.connect(recoverySigner)
|
||||
.recoverWallet(addressSignature, hash1, salt, safeKey)
|
||||
).wait();
|
||||
// await (
|
||||
// await fx.verificationGateway
|
||||
// .connect(recoverySigner)
|
||||
// .recoverWallet(addressSignature, hash1, salt, safeKey)
|
||||
// ).wait();
|
||||
|
||||
// key reset via recovery
|
||||
expect(await vg.hashFromWallet(wallet1.address)).to.eql(hash2);
|
||||
expect(await vg.walletFromHash(hash2)).to.eql(wallet1.address);
|
||||
// // key reset via recovery
|
||||
// expect(await vg.hashFromWallet(wallet1.address)).to.eql(hash2);
|
||||
// expect(await vg.walletFromHash(hash2)).to.eql(wallet1.address);
|
||||
|
||||
await fx.advanceTimeBy(safetyDelaySeconds / 2 + 1); // wait remainder the time
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds / 2 + 1); // wait remainder the time
|
||||
|
||||
// check attacker's key not set after waiting full safety delay
|
||||
await fx.call(
|
||||
walletAttacker,
|
||||
vg,
|
||||
"setPendingBLSKeyForWallet",
|
||||
[],
|
||||
await walletAttacker.Nonce(),
|
||||
);
|
||||
await fx.call(
|
||||
wallet2,
|
||||
vg,
|
||||
"setPendingBLSKeyForWallet",
|
||||
[],
|
||||
await wallet2.Nonce(),
|
||||
);
|
||||
// // check attacker's key not set after waiting full safety delay
|
||||
// await fx.call(
|
||||
// walletAttacker,
|
||||
// vg,
|
||||
// "setPendingBLSKeyForWallet",
|
||||
// [],
|
||||
// await walletAttacker.Nonce(),
|
||||
// );
|
||||
// await fx.call(
|
||||
// wallet2,
|
||||
// vg,
|
||||
// "setPendingBLSKeyForWallet",
|
||||
// [],
|
||||
// await wallet2.Nonce(),
|
||||
// );
|
||||
|
||||
expect(await vg.walletFromHash(hash1)).to.not.equal(blsWallet.address);
|
||||
expect(await vg.walletFromHash(hashAttacker)).to.not.equal(
|
||||
blsWallet.address,
|
||||
);
|
||||
expect(await vg.walletFromHash(hash2)).to.equal(blsWallet.address);
|
||||
// expect(await vg.walletFromHash(hash1)).to.not.equal(blsWallet.address);
|
||||
// expect(await vg.walletFromHash(hashAttacker)).to.not.equal(
|
||||
// blsWallet.address,
|
||||
// );
|
||||
// expect(await vg.walletFromHash(hash2)).to.equal(blsWallet.address);
|
||||
|
||||
// // verify recovered bls key can successfully call wallet-only function (eg setTrustedGateway)
|
||||
const res = await fx.callStatic(
|
||||
wallet2,
|
||||
fx.verificationGateway,
|
||||
"setTrustedBLSGateway",
|
||||
[hash2, fx.verificationGateway.address],
|
||||
3,
|
||||
);
|
||||
expect(res.successes[0]).to.equal(true);
|
||||
});
|
||||
// // // verify recovered bls key can successfully call wallet-only function (eg setTrustedGateway)
|
||||
// const res = await fx.callStatic(
|
||||
// wallet2,
|
||||
// fx.verificationGateway,
|
||||
// "setTrustedBLSGateway",
|
||||
// [hash2, fx.verificationGateway.address],
|
||||
// 3,
|
||||
// );
|
||||
// expect(res.successes[0]).to.equal(true);
|
||||
// });
|
||||
|
||||
// https://github.com/jzaki/bls-wallet/issues/141
|
||||
it("should NOT be able to recover to another wallet", async function () {
|
||||
const attackerWalletContract = await ethers.getContractAt(
|
||||
"BLSWallet",
|
||||
walletAttacker.address,
|
||||
);
|
||||
// // https://github.com/jzaki/bls-wallet/issues/141
|
||||
// it("should NOT be able to recover to another wallet", async function () {
|
||||
// const attackerWalletContract = await ethers.getContractAt(
|
||||
// "BLSWallet",
|
||||
// walletAttacker.address,
|
||||
// );
|
||||
|
||||
// Attacker users recovery signer to set their recovery hash
|
||||
const attackerRecoveryHash = ethers.utils.solidityKeccak256(
|
||||
["address", "bytes32", "bytes32"],
|
||||
[recoverySigner.address, hashAttacker, salt],
|
||||
);
|
||||
await fx.call(
|
||||
walletAttacker,
|
||||
attackerWalletContract,
|
||||
"setRecoveryHash",
|
||||
[attackerRecoveryHash],
|
||||
1,
|
||||
);
|
||||
// // Attacker users recovery signer to set their recovery hash
|
||||
// const attackerRecoveryHash = ethers.utils.solidityKeccak256(
|
||||
// ["address", "bytes32", "bytes32"],
|
||||
// [recoverySigner.address, hashAttacker, salt],
|
||||
// );
|
||||
// await fx.call(
|
||||
// walletAttacker,
|
||||
// attackerWalletContract,
|
||||
// "setRecoveryHash",
|
||||
// [attackerRecoveryHash],
|
||||
// 1,
|
||||
// );
|
||||
|
||||
// Attacker waits out safety delay
|
||||
await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
await (await attackerWalletContract.setAnyPending()).wait();
|
||||
expect(await attackerWalletContract.recoveryHash()).to.equal(
|
||||
attackerRecoveryHash,
|
||||
);
|
||||
// // Attacker waits out safety delay
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// await (await attackerWalletContract.setAnyPending()).wait();
|
||||
// expect(await attackerWalletContract.recoveryHash()).to.equal(
|
||||
// attackerRecoveryHash,
|
||||
// );
|
||||
|
||||
const addressSignature = await signWalletAddress(
|
||||
fx,
|
||||
walletAttacker.address,
|
||||
walletAttacker.privateKey,
|
||||
);
|
||||
const wallet1Key = await wallet1.PublicKey();
|
||||
// const addressSignature = await signWalletAddress(
|
||||
// fx,
|
||||
// walletAttacker.address,
|
||||
// walletAttacker.privateKey,
|
||||
// );
|
||||
// const wallet1Key = await wallet1.PublicKey();
|
||||
|
||||
// Attacker attempts to overwrite wallet 1's hash in the gateway and fails
|
||||
await expect(
|
||||
fx.verificationGateway
|
||||
.connect(recoverySigner)
|
||||
.recoverWallet(addressSignature, hashAttacker, salt, wallet1Key),
|
||||
).to.be.rejectedWith("VG: Signature not verified for wallet address");
|
||||
});
|
||||
});
|
||||
// // Attacker attempts to overwrite wallet 1's hash in the gateway and fails
|
||||
// await expect(
|
||||
// fx.verificationGateway
|
||||
// .connect(recoverySigner)
|
||||
// .recoverWallet(addressSignature, hashAttacker, salt, wallet1Key),
|
||||
// ).to.be.rejectedWith("VG: Signature not verified for wallet address");
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -1,350 +1,350 @@
|
||||
import { expect } from "chai";
|
||||
import { BigNumber } from "ethers";
|
||||
import { solidityPack } from "ethers/lib/utils";
|
||||
import { ethers, network } from "hardhat";
|
||||
// import { expect } from "chai";
|
||||
// import { BigNumber } from "ethers";
|
||||
// import { solidityPack } from "ethers/lib/utils";
|
||||
// import { ethers, network } from "hardhat";
|
||||
|
||||
import { BLSOpen, ProxyAdmin } from "../typechain";
|
||||
import { ActionData, BlsWalletWrapper } from "../clients/src";
|
||||
import Fixture from "../shared/helpers/Fixture";
|
||||
import deployAndRunPrecompileCostEstimator from "../shared/helpers/deployAndRunPrecompileCostEstimator";
|
||||
import { defaultDeployerAddress } from "../shared/helpers/deployDeployer";
|
||||
import {
|
||||
proxyAdminBundle,
|
||||
proxyAdminCall,
|
||||
} from "../shared/helpers/callProxyAdmin";
|
||||
import Create2Fixture from "../shared/helpers/Create2Fixture";
|
||||
// import { BLSOpen, ProxyAdmin } from "../typechain";
|
||||
// import { ActionData, BlsWalletWrapper } from "../clients/src";
|
||||
// import Fixture from "../shared/helpers/Fixture";
|
||||
// import deployAndRunPrecompileCostEstimator from "../shared/helpers/deployAndRunPrecompileCostEstimator";
|
||||
// import { defaultDeployerAddress } from "../shared/helpers/deployDeployer";
|
||||
// import {
|
||||
// proxyAdminBundle,
|
||||
// proxyAdminCall,
|
||||
// } from "../shared/helpers/callProxyAdmin";
|
||||
// import Create2Fixture from "../shared/helpers/Create2Fixture";
|
||||
|
||||
describe("Upgrade", async function () {
|
||||
this.beforeAll(async function () {
|
||||
// deploy the deployer contract for the transient hardhat network
|
||||
if (network.name === "hardhat") {
|
||||
// fund deployer wallet address
|
||||
const fundedSigner = (await ethers.getSigners())[0];
|
||||
await (
|
||||
await fundedSigner.sendTransaction({
|
||||
to: defaultDeployerAddress(),
|
||||
value: ethers.utils.parseEther("1"),
|
||||
})
|
||||
).wait();
|
||||
// describe("Upgrade", async function () {
|
||||
// this.beforeAll(async function () {
|
||||
// // deploy the deployer contract for the transient hardhat network
|
||||
// if (network.name === "hardhat") {
|
||||
// // fund deployer wallet address
|
||||
// const fundedSigner = (await ethers.getSigners())[0];
|
||||
// await (
|
||||
// await fundedSigner.sendTransaction({
|
||||
// to: defaultDeployerAddress(),
|
||||
// value: ethers.utils.parseEther("1"),
|
||||
// })
|
||||
// ).wait();
|
||||
|
||||
// deploy the precompile contract (via deployer)
|
||||
console.log("PCE:", await deployAndRunPrecompileCostEstimator());
|
||||
}
|
||||
});
|
||||
// // deploy the precompile contract (via deployer)
|
||||
// console.log("PCE:", await deployAndRunPrecompileCostEstimator());
|
||||
// }
|
||||
// });
|
||||
|
||||
const safetyDelaySeconds = 7 * 24 * 60 * 60;
|
||||
let fx: Fixture;
|
||||
beforeEach(async function () {
|
||||
fx = await Fixture.create();
|
||||
});
|
||||
// const safetyDelaySeconds = 7 * 24 * 60 * 60;
|
||||
// let fx: Fixture;
|
||||
// beforeEach(async function () {
|
||||
// fx = await Fixture.create();
|
||||
// });
|
||||
|
||||
it("should upgrade wallet contract", async function () {
|
||||
const MockWalletUpgraded = await ethers.getContractFactory(
|
||||
"MockWalletUpgraded",
|
||||
);
|
||||
const mockWalletUpgraded = await MockWalletUpgraded.deploy();
|
||||
// it("should upgrade wallet contract", async function () {
|
||||
// const MockWalletUpgraded = await ethers.getContractFactory(
|
||||
// "MockWalletUpgraded",
|
||||
// );
|
||||
// const mockWalletUpgraded = await MockWalletUpgraded.deploy();
|
||||
|
||||
const wallet = await fx.lazyBlsWallets[0]();
|
||||
// const wallet = await fx.lazyBlsWallets[0]();
|
||||
|
||||
// prepare call
|
||||
await proxyAdminCall(fx, wallet, "upgrade", [
|
||||
wallet.address,
|
||||
mockWalletUpgraded.address,
|
||||
]);
|
||||
// // prepare call
|
||||
// await proxyAdminCall(fx, wallet, "upgrade", [
|
||||
// wallet.address,
|
||||
// mockWalletUpgraded.address,
|
||||
// ]);
|
||||
|
||||
// Advance time one week
|
||||
const latestTimestamp = (await ethers.provider.getBlock("latest"))
|
||||
.timestamp;
|
||||
await network.provider.send("evm_setNextBlockTimestamp", [
|
||||
BigNumber.from(latestTimestamp)
|
||||
.add(safetyDelaySeconds + 1)
|
||||
.toHexString(),
|
||||
]);
|
||||
// // Advance time one week
|
||||
// const latestTimestamp = (await ethers.provider.getBlock("latest"))
|
||||
// .timestamp;
|
||||
// await network.provider.send("evm_setNextBlockTimestamp", [
|
||||
// BigNumber.from(latestTimestamp)
|
||||
// .add(safetyDelaySeconds + 1)
|
||||
// .toHexString(),
|
||||
// ]);
|
||||
|
||||
// make call
|
||||
await proxyAdminCall(fx, wallet, "upgrade", [
|
||||
wallet.address,
|
||||
mockWalletUpgraded.address,
|
||||
]);
|
||||
// // make call
|
||||
// await proxyAdminCall(fx, wallet, "upgrade", [
|
||||
// wallet.address,
|
||||
// mockWalletUpgraded.address,
|
||||
// ]);
|
||||
|
||||
const newBLSWallet = MockWalletUpgraded.attach(wallet.address);
|
||||
await (await newBLSWallet.setNewData(wallet.address)).wait();
|
||||
expect(await newBLSWallet.newData()).to.equal(wallet.address);
|
||||
});
|
||||
// const newBLSWallet = MockWalletUpgraded.attach(wallet.address);
|
||||
// await (await newBLSWallet.setNewData(wallet.address)).wait();
|
||||
// expect(await newBLSWallet.newData()).to.equal(wallet.address);
|
||||
// });
|
||||
|
||||
it("should register with new verification gateway", async function () {
|
||||
// Deploy new verification gateway
|
||||
const create2Fixture = Create2Fixture.create();
|
||||
const bls = (await create2Fixture.create2Contract("BLSOpen")) as BLSOpen;
|
||||
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin");
|
||||
const proxyAdmin2 = (await ProxyAdmin.deploy()) as ProxyAdmin;
|
||||
await proxyAdmin2.deployed();
|
||||
// it("should register with new verification gateway", async function () {
|
||||
// // Deploy new verification gateway
|
||||
// const create2Fixture = Create2Fixture.create();
|
||||
// const bls = (await create2Fixture.create2Contract("BLSOpen")) as BLSOpen;
|
||||
// const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin");
|
||||
// const proxyAdmin2 = (await ProxyAdmin.deploy()) as ProxyAdmin;
|
||||
// await proxyAdmin2.deployed();
|
||||
|
||||
const blsWalletImpl = await create2Fixture.create2Contract("BLSWallet");
|
||||
const VerificationGateway = await ethers.getContractFactory(
|
||||
"VerificationGateway",
|
||||
);
|
||||
const vg2 = await VerificationGateway.deploy(
|
||||
bls.address,
|
||||
blsWalletImpl.address,
|
||||
proxyAdmin2.address,
|
||||
);
|
||||
await (await proxyAdmin2.transferOwnership(vg2.address)).wait();
|
||||
// const blsWalletImpl = await create2Fixture.create2Contract("BLSWallet");
|
||||
// const VerificationGateway = await ethers.getContractFactory(
|
||||
// "VerificationGateway",
|
||||
// );
|
||||
// const vg2 = await VerificationGateway.deploy(
|
||||
// bls.address,
|
||||
// blsWalletImpl.address,
|
||||
// proxyAdmin2.address,
|
||||
// );
|
||||
// await (await proxyAdmin2.transferOwnership(vg2.address)).wait();
|
||||
|
||||
// Recreate hubble bls signer
|
||||
const walletOldVg = await fx.lazyBlsWallets[0]();
|
||||
const walletAddress = walletOldVg.address;
|
||||
const blsSecret = walletOldVg.privateKey;
|
||||
// // Recreate hubble bls signer
|
||||
// const walletOldVg = await fx.lazyBlsWallets[0]();
|
||||
// const walletAddress = walletOldVg.address;
|
||||
// const blsSecret = walletOldVg.privateKey;
|
||||
|
||||
const wallet = await BlsWalletWrapper.connect(
|
||||
blsSecret,
|
||||
fx.verificationGateway.address,
|
||||
fx.provider,
|
||||
);
|
||||
// Sign simple address message
|
||||
const addressMessage = solidityPack(["address"], [walletAddress]);
|
||||
const addressSignature = wallet.signMessage(addressMessage);
|
||||
// const wallet = await BlsWalletWrapper.connect(
|
||||
// blsSecret,
|
||||
// fx.verificationGateway.address,
|
||||
// fx.provider,
|
||||
// );
|
||||
// // Sign simple address message
|
||||
// const addressMessage = solidityPack(["address"], [walletAddress]);
|
||||
// const addressSignature = wallet.signMessage(addressMessage);
|
||||
|
||||
const proxyAdmin2Address = await vg2.walletProxyAdmin();
|
||||
// Get admin action to change proxy
|
||||
const bundle = await proxyAdminBundle(fx, walletOldVg, "changeProxyAdmin", [
|
||||
walletAddress,
|
||||
proxyAdmin2Address,
|
||||
]);
|
||||
const changeProxyAction = bundle.operations[0].actions[0];
|
||||
// const proxyAdmin2Address = await vg2.walletProxyAdmin();
|
||||
// // Get admin action to change proxy
|
||||
// const bundle = await proxyAdminBundle(fx, walletOldVg, "changeProxyAdmin", [
|
||||
// walletAddress,
|
||||
// proxyAdmin2Address,
|
||||
// ]);
|
||||
// const changeProxyAction = bundle.operations[0].actions[0];
|
||||
|
||||
// prepare call
|
||||
await proxyAdminCall(fx, walletOldVg, "changeProxyAdmin", [
|
||||
walletAddress,
|
||||
proxyAdmin2Address,
|
||||
]);
|
||||
// // prepare call
|
||||
// await proxyAdminCall(fx, walletOldVg, "changeProxyAdmin", [
|
||||
// walletAddress,
|
||||
// proxyAdmin2Address,
|
||||
// ]);
|
||||
|
||||
// Advance time one week
|
||||
await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// // Advance time one week
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
|
||||
const hash = walletOldVg.blsWalletSigner.getPublicKeyHash(
|
||||
walletOldVg.privateKey,
|
||||
);
|
||||
// const hash = walletOldVg.blsWalletSigner.getPublicKeyHash(
|
||||
// walletOldVg.privateKey,
|
||||
// );
|
||||
|
||||
const setExternalWalletAction: ActionData = {
|
||||
ethValue: BigNumber.from(0),
|
||||
contractAddress: vg2.address,
|
||||
encodedFunction: vg2.interface.encodeFunctionData("setBLSKeyForWallet", [
|
||||
addressSignature,
|
||||
walletOldVg.PublicKey(),
|
||||
]),
|
||||
};
|
||||
// const setExternalWalletAction: ActionData = {
|
||||
// ethValue: BigNumber.from(0),
|
||||
// contractAddress: vg2.address,
|
||||
// encodedFunction: vg2.interface.encodeFunctionData("setBLSKeyForWallet", [
|
||||
// addressSignature,
|
||||
// walletOldVg.PublicKey(),
|
||||
// ]),
|
||||
// };
|
||||
|
||||
const setTrustedBLSGatewayAction: ActionData = {
|
||||
ethValue: BigNumber.from(0),
|
||||
contractAddress: fx.verificationGateway.address,
|
||||
encodedFunction: fx.verificationGateway.interface.encodeFunctionData(
|
||||
"setTrustedBLSGateway",
|
||||
[hash, vg2.address],
|
||||
),
|
||||
};
|
||||
// const setTrustedBLSGatewayAction: ActionData = {
|
||||
// ethValue: BigNumber.from(0),
|
||||
// contractAddress: fx.verificationGateway.address,
|
||||
// encodedFunction: fx.verificationGateway.interface.encodeFunctionData(
|
||||
// "setTrustedBLSGateway",
|
||||
// [hash, vg2.address],
|
||||
// ),
|
||||
// };
|
||||
|
||||
// Upgrading the gateway requires these three steps:
|
||||
// 1. register external wallet in vg2
|
||||
// 2. change proxy admin to that in vg2
|
||||
// 3. lastly, set wallet's new trusted gateway
|
||||
//
|
||||
// If (1) or (2) are skipped, then (3) should fail, and therefore the whole
|
||||
// operation should fail.
|
||||
// // Upgrading the gateway requires these three steps:
|
||||
// // 1. register external wallet in vg2
|
||||
// // 2. change proxy admin to that in vg2
|
||||
// // 3. lastly, set wallet's new trusted gateway
|
||||
// //
|
||||
// // If (1) or (2) are skipped, then (3) should fail, and therefore the whole
|
||||
// // operation should fail.
|
||||
|
||||
{
|
||||
// Fail if setExternalWalletAction is skipped
|
||||
// {
|
||||
// // Fail if setExternalWalletAction is skipped
|
||||
|
||||
const { successes } =
|
||||
await fx.verificationGateway.callStatic.processBundle(
|
||||
walletOldVg.sign({
|
||||
nonce: BigNumber.from(2),
|
||||
actions: [
|
||||
// skip: setExternalWalletAction,
|
||||
changeProxyAction,
|
||||
setTrustedBLSGatewayAction,
|
||||
],
|
||||
}),
|
||||
);
|
||||
// const { successes } =
|
||||
// await fx.verificationGateway.callStatic.processBundle(
|
||||
// walletOldVg.sign({
|
||||
// nonce: BigNumber.from(2),
|
||||
// actions: [
|
||||
// // skip: setExternalWalletAction,
|
||||
// changeProxyAction,
|
||||
// setTrustedBLSGatewayAction,
|
||||
// ],
|
||||
// }),
|
||||
// );
|
||||
|
||||
expect(successes).to.deep.equal([false]);
|
||||
}
|
||||
// expect(successes).to.deep.equal([false]);
|
||||
// }
|
||||
|
||||
{
|
||||
// Fail if changeProxyAction is skipped
|
||||
// {
|
||||
// // Fail if changeProxyAction is skipped
|
||||
|
||||
const { successes } =
|
||||
await fx.verificationGateway.callStatic.processBundle(
|
||||
walletOldVg.sign({
|
||||
nonce: BigNumber.from(2),
|
||||
actions: [
|
||||
setExternalWalletAction,
|
||||
// skip: changeProxyAction,
|
||||
setTrustedBLSGatewayAction,
|
||||
],
|
||||
}),
|
||||
);
|
||||
// const { successes } =
|
||||
// await fx.verificationGateway.callStatic.processBundle(
|
||||
// walletOldVg.sign({
|
||||
// nonce: BigNumber.from(2),
|
||||
// actions: [
|
||||
// setExternalWalletAction,
|
||||
// // skip: changeProxyAction,
|
||||
// setTrustedBLSGatewayAction,
|
||||
// ],
|
||||
// }),
|
||||
// );
|
||||
|
||||
expect(successes).to.deep.equal([false]);
|
||||
}
|
||||
// expect(successes).to.deep.equal([false]);
|
||||
// }
|
||||
|
||||
{
|
||||
// Succeed if nothing is skipped
|
||||
// {
|
||||
// // Succeed if nothing is skipped
|
||||
|
||||
const { successes } =
|
||||
await fx.verificationGateway.callStatic.processBundle(
|
||||
walletOldVg.sign({
|
||||
nonce: BigNumber.from(2),
|
||||
actions: [
|
||||
setExternalWalletAction,
|
||||
changeProxyAction,
|
||||
setTrustedBLSGatewayAction,
|
||||
],
|
||||
}),
|
||||
);
|
||||
// const { successes } =
|
||||
// await fx.verificationGateway.callStatic.processBundle(
|
||||
// walletOldVg.sign({
|
||||
// nonce: BigNumber.from(2),
|
||||
// actions: [
|
||||
// setExternalWalletAction,
|
||||
// changeProxyAction,
|
||||
// setTrustedBLSGatewayAction,
|
||||
// ],
|
||||
// }),
|
||||
// );
|
||||
|
||||
expect(successes).to.deep.equal([true]);
|
||||
}
|
||||
// expect(successes).to.deep.equal([true]);
|
||||
// }
|
||||
|
||||
expect(await vg2.walletFromHash(hash)).not.to.equal(walletAddress);
|
||||
// expect(await vg2.walletFromHash(hash)).not.to.equal(walletAddress);
|
||||
|
||||
// Now actually perform the upgrade so we can perform some more detailed
|
||||
// checks.
|
||||
await (
|
||||
await fx.verificationGateway.processBundle(
|
||||
fx.blsWalletSigner.aggregate([
|
||||
walletOldVg.sign({
|
||||
nonce: BigNumber.from(2),
|
||||
actions: [
|
||||
setExternalWalletAction,
|
||||
changeProxyAction,
|
||||
setTrustedBLSGatewayAction,
|
||||
],
|
||||
}),
|
||||
]),
|
||||
)
|
||||
).wait();
|
||||
// // Now actually perform the upgrade so we can perform some more detailed
|
||||
// // checks.
|
||||
// await (
|
||||
// await fx.verificationGateway.processBundle(
|
||||
// fx.blsWalletSigner.aggregate([
|
||||
// walletOldVg.sign({
|
||||
// nonce: BigNumber.from(2),
|
||||
// actions: [
|
||||
// setExternalWalletAction,
|
||||
// changeProxyAction,
|
||||
// setTrustedBLSGatewayAction,
|
||||
// ],
|
||||
// }),
|
||||
// ]),
|
||||
// )
|
||||
// ).wait();
|
||||
|
||||
// Create required objects for data/contracts for checks
|
||||
const proxyAdmin = await ethers.getContractAt(
|
||||
"ProxyAdmin",
|
||||
await vg2.walletProxyAdmin(),
|
||||
);
|
||||
// // Create required objects for data/contracts for checks
|
||||
// const proxyAdmin = await ethers.getContractAt(
|
||||
// "ProxyAdmin",
|
||||
// await vg2.walletProxyAdmin(),
|
||||
// );
|
||||
|
||||
// Direct checks corresponding to each action
|
||||
expect(await vg2.walletFromHash(hash)).to.equal(walletAddress);
|
||||
expect(await vg2.hashFromWallet(walletAddress)).to.equal(hash);
|
||||
expect(await proxyAdmin.getProxyAdmin(walletAddress)).to.equal(
|
||||
proxyAdmin.address,
|
||||
);
|
||||
// // Direct checks corresponding to each action
|
||||
// expect(await vg2.walletFromHash(hash)).to.equal(walletAddress);
|
||||
// expect(await vg2.hashFromWallet(walletAddress)).to.equal(hash);
|
||||
// expect(await proxyAdmin.getProxyAdmin(walletAddress)).to.equal(
|
||||
// proxyAdmin.address,
|
||||
// );
|
||||
|
||||
const blsWallet = await ethers.getContractAt("BLSWallet", walletAddress);
|
||||
// New verification gateway pending
|
||||
expect(await blsWallet.trustedBLSGateway()).to.equal(
|
||||
fx.verificationGateway.address,
|
||||
);
|
||||
// Advance time one week
|
||||
await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// set pending
|
||||
await (await blsWallet.setAnyPending()).wait();
|
||||
// Check new verification gateway was set
|
||||
expect(await blsWallet.trustedBLSGateway()).to.equal(vg2.address);
|
||||
// const blsWallet = await ethers.getContractAt("BLSWallet", walletAddress);
|
||||
// // New verification gateway pending
|
||||
// expect(await blsWallet.trustedBLSGateway()).to.equal(
|
||||
// fx.verificationGateway.address,
|
||||
// );
|
||||
// // Advance time one week
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// // set pending
|
||||
// await (await blsWallet.setAnyPending()).wait();
|
||||
// // Check new verification gateway was set
|
||||
// expect(await blsWallet.trustedBLSGateway()).to.equal(vg2.address);
|
||||
|
||||
// Check new gateway has wallet via static call through new gateway
|
||||
const bundleResult = await vg2.callStatic.processBundle(
|
||||
fx.blsWalletSigner.aggregate([
|
||||
walletOldVg.sign({
|
||||
nonce: BigNumber.from(3),
|
||||
actions: [
|
||||
{
|
||||
ethValue: 0,
|
||||
contractAddress: vg2.address,
|
||||
encodedFunction: vg2.interface.encodeFunctionData(
|
||||
"walletFromHash",
|
||||
[hash],
|
||||
),
|
||||
},
|
||||
],
|
||||
}),
|
||||
]),
|
||||
);
|
||||
const walletFromHashAddress = ethers.utils.defaultAbiCoder.decode(
|
||||
["address"],
|
||||
bundleResult.results[0][0], // first and only operation/action result
|
||||
)[0];
|
||||
expect(walletFromHashAddress).to.equal(walletAddress);
|
||||
});
|
||||
// // Check new gateway has wallet via static call through new gateway
|
||||
// const bundleResult = await vg2.callStatic.processBundle(
|
||||
// fx.blsWalletSigner.aggregate([
|
||||
// walletOldVg.sign({
|
||||
// nonce: BigNumber.from(3),
|
||||
// actions: [
|
||||
// {
|
||||
// ethValue: 0,
|
||||
// contractAddress: vg2.address,
|
||||
// encodedFunction: vg2.interface.encodeFunctionData(
|
||||
// "walletFromHash",
|
||||
// [hash],
|
||||
// ),
|
||||
// },
|
||||
// ],
|
||||
// }),
|
||||
// ]),
|
||||
// );
|
||||
// const walletFromHashAddress = ethers.utils.defaultAbiCoder.decode(
|
||||
// ["address"],
|
||||
// bundleResult.results[0][0], // first and only operation/action result
|
||||
// )[0];
|
||||
// expect(walletFromHashAddress).to.equal(walletAddress);
|
||||
// });
|
||||
|
||||
it("should change mapping of an address to hash", async function () {
|
||||
const vg1 = fx.verificationGateway;
|
||||
// it("should change mapping of an address to hash", async function () {
|
||||
// const vg1 = fx.verificationGateway;
|
||||
|
||||
const lazyWallet1 = await fx.lazyBlsWallets[0]();
|
||||
const lazyWallet2 = await fx.lazyBlsWallets[1]();
|
||||
// const lazyWallet1 = await fx.lazyBlsWallets[0]();
|
||||
// const lazyWallet2 = await fx.lazyBlsWallets[1]();
|
||||
|
||||
const wallet1 = await BlsWalletWrapper.connect(
|
||||
lazyWallet1.privateKey,
|
||||
vg1.address,
|
||||
fx.provider,
|
||||
);
|
||||
// const wallet1 = await BlsWalletWrapper.connect(
|
||||
// lazyWallet1.privateKey,
|
||||
// vg1.address,
|
||||
// fx.provider,
|
||||
// );
|
||||
|
||||
const wallet2 = await BlsWalletWrapper.connect(
|
||||
lazyWallet2.privateKey,
|
||||
vg1.address,
|
||||
fx.provider,
|
||||
);
|
||||
// const wallet2 = await BlsWalletWrapper.connect(
|
||||
// lazyWallet2.privateKey,
|
||||
// vg1.address,
|
||||
// fx.provider,
|
||||
// );
|
||||
|
||||
const hash1 = wallet1.blsWalletSigner.getPublicKeyHash(wallet1.privateKey);
|
||||
// const hash1 = wallet1.blsWalletSigner.getPublicKeyHash(wallet1.privateKey);
|
||||
|
||||
expect(await vg1.walletFromHash(hash1)).to.equal(wallet1.address);
|
||||
expect(await vg1.hashFromWallet(wallet1.address)).to.equal(hash1);
|
||||
// expect(await vg1.walletFromHash(hash1)).to.equal(wallet1.address);
|
||||
// expect(await vg1.hashFromWallet(wallet1.address)).to.equal(hash1);
|
||||
|
||||
// wallet 2 bls key signs message containing address of wallet 1
|
||||
const addressMessage = solidityPack(["address"], [wallet1.address]);
|
||||
const addressSignature = wallet2.signMessage(addressMessage);
|
||||
// // wallet 2 bls key signs message containing address of wallet 1
|
||||
// const addressMessage = solidityPack(["address"], [wallet1.address]);
|
||||
// const addressSignature = wallet2.signMessage(addressMessage);
|
||||
|
||||
const setExternalWalletAction: ActionData = {
|
||||
ethValue: BigNumber.from(0),
|
||||
contractAddress: vg1.address,
|
||||
encodedFunction: vg1.interface.encodeFunctionData("setBLSKeyForWallet", [
|
||||
addressSignature,
|
||||
wallet2.PublicKey(),
|
||||
]),
|
||||
};
|
||||
// const setExternalWalletAction: ActionData = {
|
||||
// ethValue: BigNumber.from(0),
|
||||
// contractAddress: vg1.address,
|
||||
// encodedFunction: vg1.interface.encodeFunctionData("setBLSKeyForWallet", [
|
||||
// addressSignature,
|
||||
// wallet2.PublicKey(),
|
||||
// ]),
|
||||
// };
|
||||
|
||||
// wallet 1 submits a tx
|
||||
{
|
||||
const { successes } = await vg1.callStatic.processBundle(
|
||||
wallet1.sign({
|
||||
nonce: BigNumber.from(1),
|
||||
actions: [setExternalWalletAction],
|
||||
}),
|
||||
);
|
||||
// // wallet 1 submits a tx
|
||||
// {
|
||||
// const { successes } = await vg1.callStatic.processBundle(
|
||||
// wallet1.sign({
|
||||
// nonce: BigNumber.from(1),
|
||||
// actions: [setExternalWalletAction],
|
||||
// }),
|
||||
// );
|
||||
|
||||
expect(successes).to.deep.equal([true]);
|
||||
}
|
||||
// expect(successes).to.deep.equal([true]);
|
||||
// }
|
||||
|
||||
await (
|
||||
await fx.verificationGateway.processBundle(
|
||||
fx.blsWalletSigner.aggregate([
|
||||
wallet1.sign({
|
||||
nonce: BigNumber.from(1),
|
||||
actions: [setExternalWalletAction],
|
||||
}),
|
||||
]),
|
||||
)
|
||||
).wait();
|
||||
// await (
|
||||
// await fx.verificationGateway.processBundle(
|
||||
// fx.blsWalletSigner.aggregate([
|
||||
// wallet1.sign({
|
||||
// nonce: BigNumber.from(1),
|
||||
// actions: [setExternalWalletAction],
|
||||
// }),
|
||||
// ]),
|
||||
// )
|
||||
// ).wait();
|
||||
|
||||
// wallet 1's hash is pointed to null address
|
||||
// wallet 2's hash is now pointed to wallet 1's address
|
||||
const hash2 = wallet2.blsWalletSigner.getPublicKeyHash(wallet2.privateKey);
|
||||
// // wallet 1's hash is pointed to null address
|
||||
// // wallet 2's hash is now pointed to wallet 1's address
|
||||
// const hash2 = wallet2.blsWalletSigner.getPublicKeyHash(wallet2.privateKey);
|
||||
|
||||
await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
await fx.call(wallet1, vg1, "setPendingBLSKeyForWallet", [], 2);
|
||||
// await fx.advanceTimeBy(safetyDelaySeconds + 1);
|
||||
// await fx.call(wallet1, vg1, "setPendingBLSKeyForWallet", [], 2);
|
||||
|
||||
expect(await vg1.walletFromHash(hash1)).to.equal(
|
||||
ethers.constants.AddressZero,
|
||||
);
|
||||
expect(await vg1.walletFromHash(hash2)).to.equal(wallet1.address);
|
||||
expect(await vg1.hashFromWallet(wallet1.address)).to.equal(hash2);
|
||||
});
|
||||
});
|
||||
// expect(await vg1.walletFromHash(hash1)).to.equal(
|
||||
// ethers.constants.AddressZero,
|
||||
// );
|
||||
// expect(await vg1.walletFromHash(hash2)).to.equal(wallet1.address);
|
||||
// expect(await vg1.hashFromWallet(wallet1.address)).to.equal(hash2);
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -58,7 +58,7 @@ describe("WalletActions", async function () {
|
||||
|
||||
const initFunctionParams = BLSWallet.interface.encodeFunctionData(
|
||||
"initialize",
|
||||
[fx.verificationGateway.address],
|
||||
[fx.verificationGateway.address, ethers.constants.AddressZero],
|
||||
);
|
||||
|
||||
const calculatedAddress = ethers.utils.getCreate2Address(
|
||||
|
||||
Reference in New Issue
Block a user