Halo,
Saya menemukan bahwa pembuat paket ini telah mempertimbangkan untuk mengintegrasikan hardhat-deploy
dengan plugin pemutakhiran zeppelin terbuka untuk hardhat tetapi juga ingin menegaskan bahwa penambahan ini akan bagus.
Saat ini kami menggunakan plugin oz upgrade dan sementara kami juga ingin menggunakan plugin hardhat-deploy, kami tidak ingin mengorbankan hal-hal yang ditawarkan plugin oz kepada kami.
Halo @Remscar , pasti akan luar biasa.
Sementara itu, saya mengembangkan plugin "solusi" untuk melakukannya, saya menyalin beberapa kode dari perpustakaan @openzeppelin/upgrade-core.
Agak jelek tapi bisa berhasil (gunakan dengan risiko Anda sendiri).
Impor file ini ( setelah mengimpor hardhat-deploy ) di hardhat-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,
}
})
Penggunaan :
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
}
)
}
Sekarang ada cara bawaan untuk menggunakan Openzeppelin Transparent Proxy. Saya akan menutup masalah ini
Komentar yang paling membantu
Halo @Remscar , pasti akan luar biasa.
Sementara itu, saya mengembangkan plugin "solusi" untuk melakukannya, saya menyalin beberapa kode dari perpustakaan @openzeppelin/upgrade-core.
Agak jelek tapi bisa berhasil (gunakan dengan risiko Anda sendiri).
Impor file ini ( setelah mengimpor hardhat-deploy ) di hardhat-config.js :
Penggunaan :