Update docs
This commit is contained in:
109
test/helpers/chains.js
Normal file
109
test/helpers/chains.js
Normal file
@ -0,0 +1,109 @@
|
||||
// NOTE: this file defines some examples of CAIP-2 and CAIP-10 identifiers.
|
||||
// The following listing does not pretend to be exhaustive or even accurate. It SHOULD NOT be used in production.
|
||||
|
||||
const { ethers } = require('hardhat');
|
||||
const { mapValues } = require('./iterate');
|
||||
|
||||
// EVM (https://axelarscan.io/resources/chains?type=evm)
|
||||
const ethereum = {
|
||||
Ethereum: '1',
|
||||
optimism: '10',
|
||||
binance: '56',
|
||||
Polygon: '137',
|
||||
Fantom: '250',
|
||||
fraxtal: '252',
|
||||
filecoin: '314',
|
||||
Moonbeam: '1284',
|
||||
centrifuge: '2031',
|
||||
kava: '2222',
|
||||
mantle: '5000',
|
||||
base: '8453',
|
||||
immutable: '13371',
|
||||
arbitrum: '42161',
|
||||
celo: '42220',
|
||||
Avalanche: '43114',
|
||||
linea: '59144',
|
||||
blast: '81457',
|
||||
scroll: '534352',
|
||||
aurora: '1313161554',
|
||||
};
|
||||
|
||||
// Cosmos (https://axelarscan.io/resources/chains?type=cosmos)
|
||||
const cosmos = {
|
||||
Axelarnet: 'axelar-dojo-1',
|
||||
osmosis: 'osmosis-1',
|
||||
cosmoshub: 'cosmoshub-4',
|
||||
juno: 'juno-1',
|
||||
'e-money': 'emoney-3',
|
||||
injective: 'injective-1',
|
||||
crescent: 'crescent-1',
|
||||
kujira: 'kaiyo-1',
|
||||
'secret-snip': 'secret-4',
|
||||
secret: 'secret-4',
|
||||
sei: 'pacific-1',
|
||||
stargaze: 'stargaze-1',
|
||||
assetmantle: 'mantle-1',
|
||||
fetch: 'fetchhub-4',
|
||||
ki: 'kichain-2',
|
||||
evmos: 'evmos_9001-2',
|
||||
aura: 'xstaxy-1',
|
||||
comdex: 'comdex-1',
|
||||
persistence: 'core-1',
|
||||
regen: 'regen-1',
|
||||
umee: 'umee-1',
|
||||
agoric: 'agoric-3',
|
||||
xpla: 'dimension_37-1',
|
||||
acre: 'acre_9052-1',
|
||||
stride: 'stride-1',
|
||||
carbon: 'carbon-1',
|
||||
sommelier: 'sommelier-3',
|
||||
neutron: 'neutron-1',
|
||||
rebus: 'reb_1111-1',
|
||||
archway: 'archway-1',
|
||||
provenance: 'pio-mainnet-1',
|
||||
ixo: 'ixo-5',
|
||||
migaloo: 'migaloo-1',
|
||||
teritori: 'teritori-1',
|
||||
haqq: 'haqq_11235-1',
|
||||
celestia: 'celestia',
|
||||
ojo: 'agamotto',
|
||||
chihuahua: 'chihuahua-1',
|
||||
saga: 'ssc-1',
|
||||
dymension: 'dymension_1100-1',
|
||||
fxcore: 'fxcore',
|
||||
c4e: 'perun-1',
|
||||
bitsong: 'bitsong-2b',
|
||||
nolus: 'pirin-1',
|
||||
lava: 'lava-mainnet-1',
|
||||
'terra-2': 'phoenix-1',
|
||||
terra: 'columbus-5',
|
||||
};
|
||||
|
||||
const makeCAIP = ({ namespace, reference, account }) => ({
|
||||
namespace,
|
||||
reference,
|
||||
account,
|
||||
caip2: `${namespace}:${reference}`,
|
||||
caip10: `${namespace}:${reference}:${account}`,
|
||||
toCaip10: other => `${namespace}:${reference}:${ethers.getAddress(other.target ?? other.address ?? other)}`,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
CHAINS: mapValues(
|
||||
Object.assign(
|
||||
mapValues(ethereum, reference => ({
|
||||
namespace: 'eip155',
|
||||
reference,
|
||||
account: ethers.Wallet.createRandom().address,
|
||||
})),
|
||||
mapValues(cosmos, reference => ({
|
||||
namespace: 'cosmos',
|
||||
reference,
|
||||
account: ethers.encodeBase58(ethers.randomBytes(32)),
|
||||
})),
|
||||
),
|
||||
makeCAIP,
|
||||
),
|
||||
getLocalCAIP: account =>
|
||||
ethers.provider.getNetwork().then(({ chainId }) => makeCAIP({ namespace: 'eip155', reference: chainId, account })),
|
||||
};
|
||||
@ -32,6 +32,13 @@ module.exports = mapValues(
|
||||
reason: 'string',
|
||||
params: 'bytes',
|
||||
},
|
||||
OverrideBallot: {
|
||||
proposalId: 'uint256',
|
||||
support: 'uint8',
|
||||
voter: 'address',
|
||||
nonce: 'uint256',
|
||||
reason: 'string',
|
||||
},
|
||||
Delegation: {
|
||||
delegatee: 'address',
|
||||
nonce: 'uint256',
|
||||
|
||||
31
test/helpers/erc4337-entrypoint.js
Normal file
31
test/helpers/erc4337-entrypoint.js
Normal file
@ -0,0 +1,31 @@
|
||||
const { ethers } = require('hardhat');
|
||||
const { setCode } = require('@nomicfoundation/hardhat-network-helpers');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const INSTANCES = {
|
||||
entrypoint: {
|
||||
address: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
||||
abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bin/EntryPoint070.abi'), 'utf-8')),
|
||||
bytecode: fs.readFileSync(path.resolve(__dirname, '../bin/EntryPoint070.bytecode'), 'hex'),
|
||||
},
|
||||
sendercreator: {
|
||||
address: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C',
|
||||
abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bin/SenderCreator070.abi'), 'utf-8')),
|
||||
bytecode: fs.readFileSync(path.resolve(__dirname, '../bin/SenderCreator070.bytecode'), 'hex'),
|
||||
},
|
||||
};
|
||||
|
||||
function deployEntrypoint() {
|
||||
return Promise.all(
|
||||
Object.entries(INSTANCES).map(([name, { address, abi, bytecode }]) =>
|
||||
setCode(address, '0x' + bytecode.replace(/0x/, ''))
|
||||
.then(() => ethers.getContractAt(abi, address))
|
||||
.then(instance => ({ [name]: instance })),
|
||||
),
|
||||
).then(namedInstances => Object.assign(...namedInstances));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
deployEntrypoint,
|
||||
};
|
||||
111
test/helpers/erc4337.js
Normal file
111
test/helpers/erc4337.js
Normal file
@ -0,0 +1,111 @@
|
||||
const { ethers } = require('hardhat');
|
||||
|
||||
const SIG_VALIDATION_SUCCESS = '0x0000000000000000000000000000000000000000';
|
||||
const SIG_VALIDATION_FAILURE = '0x0000000000000000000000000000000000000001';
|
||||
|
||||
function getAddress(account) {
|
||||
return account.target ?? account.address ?? account;
|
||||
}
|
||||
|
||||
function pack(left, right) {
|
||||
return ethers.solidityPacked(['uint128', 'uint128'], [left, right]);
|
||||
}
|
||||
|
||||
function packValidationData(validAfter, validUntil, authorizer) {
|
||||
return ethers.solidityPacked(
|
||||
['uint48', 'uint48', 'address'],
|
||||
[
|
||||
validAfter,
|
||||
validUntil,
|
||||
typeof authorizer == 'boolean'
|
||||
? authorizer
|
||||
? SIG_VALIDATION_SUCCESS
|
||||
: SIG_VALIDATION_FAILURE
|
||||
: getAddress(authorizer),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
function packInitCode(factory, factoryData) {
|
||||
return ethers.solidityPacked(['address', 'bytes'], [getAddress(factory), factoryData]);
|
||||
}
|
||||
|
||||
function packPaymasterAndData(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData) {
|
||||
return ethers.solidityPacked(
|
||||
['address', 'uint128', 'uint128', 'bytes'],
|
||||
[getAddress(paymaster), paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData],
|
||||
);
|
||||
}
|
||||
|
||||
/// Represent one user operation
|
||||
class UserOperation {
|
||||
constructor(params) {
|
||||
this.sender = getAddress(params.sender);
|
||||
this.nonce = params.nonce;
|
||||
this.factory = params.factory ?? undefined;
|
||||
this.factoryData = params.factoryData ?? '0x';
|
||||
this.callData = params.callData ?? '0x';
|
||||
this.verificationGas = params.verificationGas ?? 10_000_000n;
|
||||
this.callGas = params.callGas ?? 100_000n;
|
||||
this.preVerificationGas = params.preVerificationGas ?? 100_000n;
|
||||
this.maxPriorityFee = params.maxPriorityFee ?? 100_000n;
|
||||
this.maxFeePerGas = params.maxFeePerGas ?? 100_000n;
|
||||
this.paymaster = params.paymaster ?? undefined;
|
||||
this.paymasterVerificationGasLimit = params.paymasterVerificationGasLimit ?? 0n;
|
||||
this.paymasterPostOpGasLimit = params.paymasterPostOpGasLimit ?? 0n;
|
||||
this.paymasterData = params.paymasterData ?? '0x';
|
||||
this.signature = params.signature ?? '0x';
|
||||
}
|
||||
|
||||
get packed() {
|
||||
return {
|
||||
sender: this.sender,
|
||||
nonce: this.nonce,
|
||||
initCode: this.factory ? packInitCode(this.factory, this.factoryData) : '0x',
|
||||
callData: this.callData,
|
||||
accountGasLimits: pack(this.verificationGas, this.callGas),
|
||||
preVerificationGas: this.preVerificationGas,
|
||||
gasFees: pack(this.maxPriorityFee, this.maxFeePerGas),
|
||||
paymasterAndData: this.paymaster
|
||||
? packPaymasterAndData(
|
||||
this.paymaster,
|
||||
this.paymasterVerificationGasLimit,
|
||||
this.paymasterPostOpGasLimit,
|
||||
this.paymasterData,
|
||||
)
|
||||
: '0x',
|
||||
signature: this.signature,
|
||||
};
|
||||
}
|
||||
|
||||
hash(entrypoint, chainId) {
|
||||
const p = this.packed;
|
||||
const h = ethers.keccak256(
|
||||
ethers.AbiCoder.defaultAbiCoder().encode(
|
||||
['address', 'uint256', 'bytes32', 'bytes32', 'uint256', 'uint256', 'uint256', 'uint256'],
|
||||
[
|
||||
p.sender,
|
||||
p.nonce,
|
||||
ethers.keccak256(p.initCode),
|
||||
ethers.keccak256(p.callData),
|
||||
p.accountGasLimits,
|
||||
p.preVerificationGas,
|
||||
p.gasFees,
|
||||
ethers.keccak256(p.paymasterAndData),
|
||||
],
|
||||
),
|
||||
);
|
||||
return ethers.keccak256(
|
||||
ethers.AbiCoder.defaultAbiCoder().encode(['bytes32', 'address', 'uint256'], [h, getAddress(entrypoint), chainId]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SIG_VALIDATION_SUCCESS,
|
||||
SIG_VALIDATION_FAILURE,
|
||||
packValidationData,
|
||||
packInitCode,
|
||||
packPaymasterAndData,
|
||||
UserOperation,
|
||||
};
|
||||
58
test/helpers/erc7579.js
Normal file
58
test/helpers/erc7579.js
Normal file
@ -0,0 +1,58 @@
|
||||
const { ethers } = require('hardhat');
|
||||
|
||||
const MODULE_TYPE_VALIDATOR = 1;
|
||||
const MODULE_TYPE_EXECUTOR = 2;
|
||||
const MODULE_TYPE_FALLBACK = 3;
|
||||
const MODULE_TYPE_HOOK = 4;
|
||||
|
||||
const EXEC_TYPE_DEFAULT = '0x00';
|
||||
const EXEC_TYPE_TRY = '0x01';
|
||||
|
||||
const CALL_TYPE_CALL = '0x00';
|
||||
const CALL_TYPE_BATCH = '0x01';
|
||||
const CALL_TYPE_DELEGATE = '0xff';
|
||||
|
||||
const encodeMode = ({
|
||||
callType = '0x00',
|
||||
execType = '0x00',
|
||||
selector = '0x00000000',
|
||||
payload = '0x00000000000000000000000000000000000000000000',
|
||||
} = {}) =>
|
||||
ethers.solidityPacked(
|
||||
['bytes1', 'bytes1', 'bytes4', 'bytes4', 'bytes22'],
|
||||
[callType, execType, '0x00000000', selector, payload],
|
||||
);
|
||||
|
||||
const encodeSingle = (target, value = 0n, data = '0x') =>
|
||||
ethers.solidityPacked(['address', 'uint256', 'bytes'], [target.target ?? target.address ?? target, value, data]);
|
||||
|
||||
const encodeBatch = (...entries) =>
|
||||
ethers.AbiCoder.defaultAbiCoder().encode(
|
||||
['(address,uint256,bytes)[]'],
|
||||
[
|
||||
entries.map(entry =>
|
||||
Array.isArray(entry)
|
||||
? [entry[0].target ?? entry[0].address ?? entry[0], entry[1] ?? 0n, entry[2] ?? '0x']
|
||||
: [entry.target.target ?? entry.target.address ?? entry.target, entry.value ?? 0n, entry.data ?? '0x'],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
const encodeDelegate = (target, data = '0x') =>
|
||||
ethers.solidityPacked(['address', 'bytes'], [target.target ?? target.address ?? target, data]);
|
||||
|
||||
module.exports = {
|
||||
MODULE_TYPE_VALIDATOR,
|
||||
MODULE_TYPE_EXECUTOR,
|
||||
MODULE_TYPE_FALLBACK,
|
||||
MODULE_TYPE_HOOK,
|
||||
EXEC_TYPE_DEFAULT,
|
||||
EXEC_TYPE_TRY,
|
||||
CALL_TYPE_CALL,
|
||||
CALL_TYPE_BATCH,
|
||||
CALL_TYPE_DELEGATE,
|
||||
encodeMode,
|
||||
encodeSingle,
|
||||
encodeBatch,
|
||||
encodeDelegate,
|
||||
};
|
||||
@ -128,6 +128,23 @@ class GovernorHelper {
|
||||
return await this.governor[method](...args);
|
||||
}
|
||||
|
||||
async overrideVote(vote = {}) {
|
||||
let method = 'castOverrideVote';
|
||||
let args = [this.id, vote.support];
|
||||
|
||||
vote.reason = vote.reason ?? '';
|
||||
|
||||
if (vote.signature) {
|
||||
let message = this.forgeMessage(vote);
|
||||
message.reason = message.reason ?? '';
|
||||
const sign = await vote.signature(this.governor, message);
|
||||
method = 'castOverrideVoteBySig';
|
||||
args.push(vote.voter, vote.reason ?? '', sign);
|
||||
}
|
||||
|
||||
return await this.governor[method](...args);
|
||||
}
|
||||
|
||||
/// Clock helpers
|
||||
async waitForSnapshot(offset = 0n) {
|
||||
const timepoint = await this.governor.proposalSnapshot(this.id);
|
||||
|
||||
@ -26,7 +26,7 @@ const upgradeableSlot = (contractName, offset) => {
|
||||
// Try to get the artifact paths, will throw if it doesn't exist
|
||||
artifacts._getArtifactPathSync(`${contractName}Upgradeable`);
|
||||
return offset + ethers.toBigInt(erc7201Slot(erc7201format(contractName)));
|
||||
} catch (_) {
|
||||
} catch {
|
||||
return offset;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user