рдирдорд╕реНрддреЗ,
рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдЗрд╕ рдкреИрдХреЗрдЬ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдиреЗ рдкрд╣рд▓реЗ рд╣реА рд╣рд╛рд░реНрдбрд╣реИрдЯ рдХреЗ рд▓рд┐рдП рдЦреБрд▓реЗ рдЬреЗрдкреЗрд▓рд┐рди рдЕрдкрдЧреНрд░реЗрдб рдкреНрд▓рдЧрдЗрди рдХреЗ рд╕рд╛рде hardhat-deploy
рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдкрд░ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рднреА рдкреНрд░рддрд┐рдзреНрд╡рдирд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ рдХрд┐ рдпрд╣ рдЕрддрд┐рд░рд┐рдХреНрдд рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред
рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╣рдо oz рдЕрдкрдЧреНрд░реЗрдб рдкреНрд▓рдЧрдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдЬрдмрдХрд┐ рд╣рдо рд╣рд╛рд░реНрдбрд╣реИрдЯ-рдбрд┐рдкреНрд▓реЙрдп рдкреНрд▓рдЧрдЗрди рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рдо рдЙрди рдЪреАрдЬреЛрдВ рдХрд╛ рддреНрдпрд╛рдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬреЛ oz рдкреНрд▓рдЧрдЗрди рд╣рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рд╣реИрд▓реЛ @Remscar , рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред
рдЗрд╕ рдмреАрдЪ, рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб" рдкреНрд▓рдЧрдЗрди рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛, рдореИрдВрдиреЗ @ openzeppelin/upgrad-core рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдХреБрдЫ рдХреЛрдб рдХреЙрдкреА рдХрд┐рдПред
рдпрд╣ рдереЛрдбрд╝рд╛ рдмрджрд╕реВрд░рдд рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рдЗрд╕реЗ рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдкрд░ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░реЗрдВ)ред
рд╣рд╛рд░реНрдбрд╣реИрдЯ-config.js рдореЗрдВ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЖрдпрд╛рдд рдХрд░реЗрдВ (рд╣рд╛рд░реНрдбрд╣реИрдЯ-рддреИрдирд╛рддреА рдЖрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж):
const { extendEnvironment } = require("hardhat/config")
const AdminUpgradeabilityProxy = require("@openzeppelin/upgrades-core/artifacts/contracts/proxy/AdminUpgradeabilityProxy.sol/AdminUpgradeabilityProxy.json")
const ProxyAdmin = require("@openzeppelin/upgrades-core/artifacts/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json")
const { assertUpgradeSafe, getVersion, getUnlinkedBytecode } = require("@openzeppelin/upgrades-core")
const { readValidations } = require("@openzeppelin/hardhat-upgrades/dist/validations")
const getSigner = async address => {
const signers = await hre.ethers.getSigners()
return signers.find(signer => signer.address === address)
}
const getInitializerData = (ImplFactory, args = [], initializer) => {
if (initializer === false) {
return "0x"
}
const allowNoInitialization = initializer === undefined && args.length === 0
initializer = initializer ?? "initialize"
try {
const fragment = ImplFactory.interface.getFunction(initializer)
return ImplFactory.interface.encodeFunctionData(fragment, args)
} catch (e) {
if (e instanceof Error) {
if (allowNoInitialization && e.message.includes("no matching function")) {
return "0x"
}
}
throw e
}
}
const deployProxyAdmin = async (owner) => {
const { deployments } = hre
const { deploy } = deployments
return await deploy("ProxyAdmin", {
contract: ProxyAdmin,
from: owner,
log: true,
})
}
const deployOrUpgrade = async (firstImplName, opts, { initializer, postUpgrade, upgrades }) => {
const { deployments } = hre
const { deploy } = deployments
let proxyAdmin
try {
proxyAdmin = await deployments.get("ProxyAdmin")
} catch (error) {
proxyAdmin = await deployProxyAdmin(opts.from)
}
const proxyName = `${firstImplName}Proxy`
const firstImpl = await deploy(firstImplName, opts)
const initData = getInitializerData(
await ethers.getContractFactory(firstImplName),
initializer && initializer.args ? initializer.args : [],
initializer ? initializer.method : false
)
const proxy = await deploy(proxyName, {
contract: AdminUpgradeabilityProxy,
from: opts.from,
log: true,
args: [firstImpl.address, proxyAdmin.address, initData],
})
if (upgrades && upgrades.length > 0) {
let previousImplName, newImplName
if (upgrades.length === 1) {
previousImplName = firstImplName
newImplName = upgrades[0]
} else {
newImplName = upgrades.pop()
previousImplName = upgrades.pop()
for (oldUpgrade in upgrades) {
// unsure previous upgrades exists
await deployments.get(upgrades[oldUpgrade])
}
}
if (previousImplName === newImplName) throw new Error("Same implementation, can't upgrade.")
const newImplFactory = await ethers.getContractFactory(newImplName)
const validations = await readValidations(hre)
const unlinkedBytecode = getUnlinkedBytecode(validations, newImplFactory.bytecode)
const version = getVersion(unlinkedBytecode, newImplFactory.bytecode)
assertUpgradeSafe(validations, version, {
unsafeAllowCustomTypes: false,
unsafeAllowLinkedLibraries: false,
})
const signer = await getSigner(opts.from)
const proxyAdminContract = await ethers.getContractAt(proxyAdmin.abi, proxyAdmin.address, signer)
const previousImpl = await deployments.get(previousImplName)
const actualImpl = await proxyAdminContract.getProxyImplementation(proxy.address)
const newImpl = await deploy(newImplName, {
from: opts.from,
log: true,
})
if (newImpl.newlyDeployed)
if (actualImpl == previousImpl.address) {
console.log(`Upgrading from ${previousImplName} to ${newImplName}`)
if (postUpgrade && postUpgrade.method && postUpgrade.args) {
const upgradeData = getInitializerData(await ethers.getContractFactory(newImplName), postUpgrade.args, postUpgrade.method)
await proxyAdminContract.upgradeAndCall(proxy.address, newImpl.address, upgradeData)
} else await proxyAdminContract.upgrade(proxy.address, newImpl.address)
} else throw new Error(`Proxy is actually pointing on: ${actualImpl}`)
}
return proxy
}
extendEnvironment(hre => {
hre.myPlugin = {
deployOrUpgrade,
}
})
рдЙрдкрдпреЛрдЧ:
module.exports = async ({ getNamedAccounts, myPlugin }) => {
const { deployer } = await getNamedAccounts()
// This will deploy the "Contract" with a proxy and a proxyAdmin if it doesn't exist.
const proxy = await myPlugin.deployOrUpgrade(
"Contract",
{ from: deployer, log: true },
{
initializer: { method: "initialize", args: [] },
// bellow attributes for upgrading
postUpgrade: { method: "postUpgrade", args: [] }, // method to exec after upgrade
upgrades: ["ContractV2", "ContractV3"], // you should keep the list of upgrades and add the new one at the last
}
)
}
Openzeppelin рдкрд╛рд░рджрд░реНрд╢реА рдкреНрд░реЙрдХреНрд╕реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдм рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рддрд░реАрдХрд╛ рд╣реИред рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░ рджреВрдВрдЧрд╛
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рд╣реИрд▓реЛ @Remscar , рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред
рдЗрд╕ рдмреАрдЪ, рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб" рдкреНрд▓рдЧрдЗрди рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛, рдореИрдВрдиреЗ @ openzeppelin/upgrad-core рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдХреБрдЫ рдХреЛрдб рдХреЙрдкреА рдХрд┐рдПред
рдпрд╣ рдереЛрдбрд╝рд╛ рдмрджрд╕реВрд░рдд рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рдЗрд╕реЗ рдЕрдкрдиреЗ рдЬреЛрдЦрд┐рдо рдкрд░ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░реЗрдВ)ред
рд╣рд╛рд░реНрдбрд╣реИрдЯ-config.js рдореЗрдВ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЖрдпрд╛рдд рдХрд░реЗрдВ (рд╣рд╛рд░реНрдбрд╣реИрдЯ-рддреИрдирд╛рддреА рдЖрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж):
рдЙрдкрдпреЛрдЧ: