Hardhat-deploy: Pertanyaan tentang penerapan kontrak yang Dapat Diupgrade

Dibuat pada 8 Jun 2021  ·  9Komentar  ·  Sumber: wighawag/hardhat-deploy

Apa cara yang benar untuk menerapkan kontrak yang dapat diupgrade OpenZeppelin?
OpenZeppelin upgrdable memiliki fungsi initialize() default yang dipanggil oleh plugin upgrade hardhat.
Tidak ada panggilan otomatis dari hardhat-deploy, hanya metode pasca-upgrade yang dapat dipanggil.

Haruskah saya menyebarkan kontrak terlebih dahulu melalui skrip di folder penyebaran dan kemudian memanggil fungsi inisialisasi dari beberapa skrip di luar folder penyebaran? Atau apakah ada cara untuk memasukkan fungsi panggilan initialize() dari folder penyebaran itu sendiri?

Komentar yang paling membantu

Inisialisasi ulang fungsi untuk proxy

Saya menambahkan opsi baru (bukan methodName yang masih tersedia) di hardhat-deploy 0.8.0

lihat https://github.com/wighawag/template-ethereum-contracts/blob/595c1b5ec9cdf1276f4d3a43b4825bcef78bd2cd/deploy/004_deploy_erc20_always_proxied_via_openzeppelin_proxy.ts#L12 -L26

Beri tahu saya jika Anda mengalami masalah apa pun

Semua 9 komentar

Cara hardhat-deploy mempertimbangkan penerapan skrip secara default adalah bahwa skrip tersebut idempoten. Hal yang sama berlaku untuk penyebaran proxy. Ini membuatnya bagus untuk pengembangan/penerapan karena Anda hanya perlu memikirkan status apa yang Anda inginkan dan hardhat-deploy akan membuat segalanya mencapai status itu,

jadi untuk menjawab pertanyaan Anda, yang biasanya saya lakukan adalah membuat fungsi inisialisasi idempoten juga, jadi alih-alih membuangnya, lewati saja jika sudah diinisialisasi. Dengan demikian saya dapat menambahkan fungsi itu sebagai fungsi postUpgrade dan semuanya berfungsi dengan baik. Dalam pengembangan saya bahkan dapat mengubah fungsi inisialisasi untuk melakukan sesuatu ketika saya memutakhirkan jika diperlukan.

Untuk skenario yang lebih kompleks, Anda dapat mengatur setiap pemutakhiran dalam skrip penerapan yang terpisah.

Ada fitur tidak berdokumen yang dapat berubah: parameter upgradeIndex yang memungkinkan Anda menentukan skrip penerapan yang perlu dijalankan secara berurutan.

Ini bagus untuk pengujian karena Anda dapat menguji proxy Anda kapan saja di antara riwayat pemutakhiran dan memastikan semuanya berfungsi.

Terima kasih atas balasan cepat Anda.
Sepertinya saya berhasil membuat semua bekerja dengan lancar. Saya menggunakan deploy() dan kemudian execute dengan fungsi $# initialize 2$#$ dari kontrak dasar OpenZeppelin Initializable . execute() mengembalikan nilai true dan ini membuatnya tidak berjalan ketika saya memutakhirkan kontrak:

// deploy/01_deploy_skin_rewards.js

module.exports = async ({
  getNamedAccounts,
  deployments,
}) => {
  const {deploy} = deployments;
  const {deployer} = await getNamedAccounts();
  await deploy('SkinRewards', {
    from: deployer,
    proxy: {
      owner: deployer,
      proxyContract: 'OpenZeppelinTransparentProxy',
    },
    args: [],
    log: true,
  });
};
module.exports.tags = ['SkinRewards'];

lalu

// deploy/02_init_skin_rewards.js

require('dotenv').config();
const RewardPeriods = ethers.BigNumber.from(process.env.REWARD_PERIODS);
module.exports = async ({getNamedAccounts, deployments}) => {
  const { deployer } = await getNamedAccounts();
  const SnookGame = await deployments.get('SnookGame');
  const SnookState = await deployments.get('SnookState');
  const SnookToken = await deployments.get('SnookToken');
  const SkillToken = await deployments.get('SkillToken');
  const Afterdeath = await deployments.get('Afterdeath');
  const Treasury = await deployments.get('Treasury');

  await deployments.execute(
    'SkinRewards',
    {from:deployer},
    'initialize',
    RewardPeriods,
    Treasury.address,
    SnookGame.address,
    SnookState.address,
    SnookToken.address,
    SkillToken.address,
    Afterdeath.address
  );
  deployments.log('Initialized SkinRewards');
  return true;
};
module.exports.tags = ['initSkinRewards'];
module.exports.id = 'initSkinRewards';

Bisakah metode ini dianggap _praktik yang baik_? Apakah itu cara Anda mencarinya?

Seperti yang saya sebutkan di atas, dalam SkinRewards saya mewarisi dari kontrak Initializable OpenZeppelin yang mendefinisikan fungsi initialize() untuk dipanggil terlebih dahulu. Jadi saya tidak melihat bagaimana saya bisa menjalankannya setelah peningkatan. Bisakah Anda menjelaskan? Terima kasih

Kedengarannya bagus, kerugiannya dibandingkan dengan menggunakan methodName ("postUpgrade") adalah Anda menjalankan 2 tx alih-alih 1

Jika Anda membuat fungsi inisialisasi idempoten, yaitu dapat dipanggil beberapa kali tanpa membuang dengan memastikan panggilan lebih lanjut tidak akan mengubah status (dengan hanya melewatkan jika sudah diinisialisasi), maka Anda dapat menggunakannya melalui opsi methodName . penyebaran pertama akan mengeksekusinya juga.

Catatan, karena Anda menggunakan argumen dan fungsi penerapan diatur sehingga Anda dapat dengan mudah mematikan opsi proxy dan memiliki kontrak yang tidak dapat diubah, opsi methodName menggunakan opsi args untuk argumen.
Ini berarti konstruktor implementasi proxy juga perlu memiliki argumen ini. Jika Anda tidak pernah berniat untuk menggunakan kontrak tanpa proxy, Anda tidak dapat melakukan apa-apa dengan argumen.

Sebenarnya untuk kenyamanan jika kontrak implementasi memiliki konstruktor nol arg, itu mengabaikan konstruktor sepenuhnya tetapi saya tidak yakin itu ide yang bagus.

Ini adalah skrip dengan opsi methodName :

// deploy/01_deploy_skin_rewards.js

module.exports = async ({
  getNamedAccounts,
  deployments,
}) => {
  const {deploy} = deployments;
  const {deployer} = await getNamedAccounts();
  await deploy('SkinRewards', {
    from: deployer,
    proxy: {
      methodName: 'initialize`,
      owner: deployer,
      proxyContract: 'OpenZeppelinTransparentProxy',
    },
    args: [
      RewardPeriods,
      Treasury.address,
      SnookGame.address,
      SnookState.address,
      SnookToken.address,
      SkillToken.address,
      Afterdeath.address
    ],
    log: true,
  });
};
module.exports.tags = ['SkinRewards'];

_Jika Anda membuat fungsi inisialisasi idempoten, yaitu dapat dipanggil beberapa kali tanpa membuang dengan memastikan panggilan lebih lanjut tidak akan mengubah status (dengan hanya melewatkan jika sudah diinisialisasi), maka Anda dapat menggunakannya melalui opsi methodName. penyebaran pertama akan mengeksekusinya juga._

Ini berarti bahwa kita tidak dapat menggunakan fungsi initialize() SEBAGAIMANA ADANYA dari https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/release-v4.0/contracts/proxy/utils/Initializable.sol .

@freebyte memang

Saya akan mempertimbangkan untuk menambahkan opsi untuk mendapatkan perilaku semacam ini

Terima kasih banyak!

Pertanyaan lain adalah tentang menggunakan kontrak yang dikerahkan. Khususnya, saya bertanya tentang Uniswap .

Dari bagian dokumen plugin ini saya tidak melihat bagaimana saya memberikan alamat kontrak Uniswap yang digunakan. Uniswap NPM hadir dengan folder build dengan artifak tetapi bagaimana cara membuat plugin mengetahui tentang kontrak di alamat tertentu? Kami tidak ingin menggunakan eter dalam skrip penerapan, bukan?

Kode berikut BUKAN yang kita inginkan dalam skrip penerapan:

const { ethers } = require("hardhat");

const UniswapV2FactoryArtifact = require('@uniswap/v2-core/build/UniswapV2Factory.json');
const UniswapV2FactoryAddress = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f';

module.exports = async ({getNamedAccounts, deployments}) => {
  const {deployer} = await getNamedAccounts();
  const UniswapFactory = await ethers.getContractAt(UniswapV2FactoryArtifact.abi, UniswapV2FactoryAddress);
// continue...

Bagaimana cara mendapatkan penyebaran Uniswap ke deployments var?

untuk kontrak yang sudah dikerahkan, yang terbaik adalah membuat file untuk mereka di folder penerapan yang sesuai
jadi untuk mainnet uniswap dan dengan asumsi Anda memiliki jaringan mainnet yang dikonfigurasi di hardhat.config.js, Anda dapat membuat file "deployments/mainnet/UniswapFactory.json". Minimal membutuhkan alamat dan bidang abi

maka Anda dapat mengaksesnya melalui penerapan saat berada di jaringan itu

Tautan dokumen yang Anda arahkan untuk memungkinkan Anda mengakses artefak (jadi folder build uniswap) atau menggunakan skrip, tetapi yang terakhir hanya berfungsi jika proyek yang dimaksud mengekspos skrip penerapan ini di suatu tempat

Saya melakukannya di proyek saya sendiri seperti https://github.com/wighawag/universal-forwarder yang memungkinkan pengguna untuk menginstal paket npm dan mereka mendapatkan seluruh proyek digunakan dalam pengujian mereka atau di jaringan mereka sendiri. Tapi uniswap tidak menyediakan itu

Besar. Terima kasih banyak.

Inisialisasi ulang fungsi untuk proxy

Saya menambahkan opsi baru (bukan methodName yang masih tersedia) di hardhat-deploy 0.8.0

lihat https://github.com/wighawag/template-ethereum-contracts/blob/595c1b5ec9cdf1276f4d3a43b4825bcef78bd2cd/deploy/004_deploy_erc20_always_proxied_via_openzeppelin_proxy.ts#L12 -L26

Beri tahu saya jika Anda mengalami masalah apa pun

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

jaypaik picture jaypaik  ·  13Komentar

smartcontracts picture smartcontracts  ·  20Komentar

gitpusha picture gitpusha  ·  6Komentar

lcswillems picture lcswillems  ·  14Komentar

jsidorenko picture jsidorenko  ·  3Komentar