Update docs

This commit is contained in:
github-actions
2025-01-22 04:00:10 +00:00
parent edf6031131
commit 0dda004024
124 changed files with 8439 additions and 1170 deletions

109
test/helpers/chains.js Normal file
View 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 })),
};

View File

@ -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',

View 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
View 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
View 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,
};

View File

@ -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);

View File

@ -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;
}
};