UNPKG

@solarity/hardhat-migrate

Version:
135 lines 6.13 kB
import { BaseContract, defineProperties, } from "ethers"; import { Adapter } from "./Adapter.js"; import { MinimalContract } from "../MinimalContract.js"; import { UNKNOWN_TRANSACTION_NAME } from "../../../constants.js"; import { bytecodeToString, fillParameters, getMethodString } from "../../utils/index.js"; import { Stats } from "../../tools/Stats.js"; import { Reporter } from "../../tools/reporters/Reporter.js"; import { networkManager } from "../../tools/network/NetworkManager.js"; import { TransactionRunner } from "../../tools/runners/TransactionRunner.js"; import { TransactionProcessor } from "../../tools/storage/TransactionProcessor.js"; import { migratorConfig } from "../../tools/network/EthersProvider.js"; export class BaseAdapter extends Adapter { getRawBytecode(instance) { return bytecodeToString(instance.bytecode); } async fromInstance(instance, parameters) { return new MinimalContract(this.getRawBytecode(instance), this.getInterface(instance), this.getContractName(instance, parameters)); } async toInstance(instance, address, parameters) { const signer = await networkManager.getSigner(parameters.from); const contractName = this.getContractName(instance, parameters); let contract = new BaseContract(address, this.getInterface(instance), signer); contract = this._insertAddressGetter(contract, address); contract = await this._overrideConnectMethod(contract, this.getInterface(instance), contractName); return this._insertHandlers(contract, contractName); } _insertHandlers(contract, contractName) { const methodSet = new Set(); for (const methodFragments of this._getContractFunctionFragments(contract.interface)) { if (methodFragments.stateMutability === "view" || methodFragments.stateMutability === "pure") { continue; } const methodName = methodFragments.format(); const shortName = methodName.split("(")[0]; const oldMethod = contract[methodName]; const newMethod = this._wrapOldMethod(contractName, methodName, methodFragments, oldMethod, contract.runner); defineProperties(newMethod, { name: oldMethod.name, getFragment: oldMethod.getFragment, estimateGas: oldMethod.estimateGas, populateTransaction: oldMethod.populateTransaction, send: oldMethod.send, staticCall: oldMethod.staticCall, staticCallResult: oldMethod.staticCallResult, }); Object.defineProperty(newMethod, "fragment", oldMethod.fragment); contract[methodName] = newMethod; if (!methodSet.has(shortName)) { contract[shortName] = newMethod; methodSet.add(shortName); } else { contract[shortName] = undefined; } } return contract; } async _overrideConnectMethod(contract, contractInterface, contractName) { const defaultRunner = await networkManager.getSigner(); contract.connect = (runner) => { const newContract = new BaseContract(contract.target, contractInterface, runner ?? defaultRunner); return this._insertHandlers(newContract, contractName); }; return contract; } _insertAddressGetter(contract, contractAddress) { contract.address = contractAddress; return contract; } _getContractFunctionFragments(contractInterface) { const result = []; contractInterface.forEachFunction((fragment) => { result.push(fragment); }); return result; } _wrapOldMethod(contractName, methodName, methodFragments, oldMethod, runner) { return async (...args) => { const tx = await oldMethod.populateTransaction(...args); tx.from = runner.address || (await runner.getAddress()); await fillParameters(tx); const methodString = getMethodString(contractName, methodName, methodFragments, args); const keyFields = this._getKeyFieldsFromTransaction(tx); if (migratorConfig.execution.continue) { return this._recoverTransaction(methodString, keyFields, oldMethod, args); } return this._sendTransaction(methodString, keyFields, oldMethod, args); }; } async _recoverTransaction(methodString, tx, oldMethod, args) { try { const savedTransaction = TransactionProcessor?.tryRestoreSavedTransaction(tx); Reporter.notifyTransactionRecovery(methodString, savedTransaction); return this._wrapTransactionFieldsToSave(savedTransaction); } catch { Reporter.notifyTransactionSendingInsteadOfRecovery(methodString); return this._sendTransaction(methodString, tx, oldMethod, args); } } async _sendTransaction(methodString, tx, oldMethod, args) { const txResponse = (await oldMethod(...args)); const saveMetadata = { migrationNumber: Stats.currentMigration, methodName: methodString, }; await TransactionRunner.reportTransactionResponse(txResponse, methodString); TransactionProcessor?.saveTransaction(tx, (await txResponse.wait()), saveMetadata); return txResponse; } _wrapTransactionFieldsToSave(data) { return { wait(_confirms) { return data.receipt; }, }; } _getKeyFieldsFromTransaction(tx) { return { name: this._getTransactionName(tx), data: tx.data, from: tx.from, chainId: tx.chainId, value: tx.value, to: tx.to, }; } _getTransactionName(tx) { if (tx.customData === undefined || tx.customData.txName === undefined) { return UNKNOWN_TRANSACTION_NAME; } return tx.customData.txName; } } //# sourceMappingURL=BaseAdapter.js.map