Contract-Deployment

Hardhat:如何使用自定義簽名者進行部署?

  • October 9, 2022

通常,要將合約部署到網路,我們在網路配置部分指定私鑰accounts,如下所示,這些帳戶用於簽署交易。

module.exports = {
 defaultNetwork: "rinkeby",
 networks: {
   hardhat: {
   },
   rinkeby: {
     url: "https://eth-rinkeby.alchemyapi.io/v2/1234",
     accounts: [privateKey1, privateKey2, ...]
   }
 },

但是我們需要使用自定義簽名者來代替對交易進行簽名。作為部署過程一部分的所有事務都需要通過此自定義簽名者進行簽名。

如何使用 Hardhat/ethers.js 做到這一點?

編輯

這個想法類似於使用元遮罩錢包簽名,不同之處在於:

  1. 整個操作都在後端,因此沒有window.ethereum可用的
  2. 當 Hardhat 想要部署合約時,也需要呼叫這個簽名過程。
  3. 我們得到了一個庫,它有一個sign方法,需要使用一些參數來呼叫,例如abi,rawTransactionkeys. 我試圖弄清楚如何讓 Hardhat 在部署期間呼叫此sign方法以及所需的參數。

編輯 2

禮貌@Ad-h0c,我知道我真正想要的是Custom Provider在部署過程中使用的安全帽。很長一段時間以來,我們一直在 Truffle 中使用類似於this的東西來執行此操作,但更複雜的是,它還包含帶有 tx 原始參數的簽名函式。因此,要求變為:

  1. 為 Hardhat 指定一個自定義提供程序以在部署期間使用
  2. 為自定義提供程序功能提供接受raw transaction數據的能力,這些數據將在內部使用我們自己的庫進行簽名,然後發送到區塊鏈

如果您問如何通過錢包簽署交易?例如,metamask,你可以按照下面的程式碼。

const foo = async (params) => {
   const provider = new ethers.providers.Web3Provider(window.ethereum);
   await provider.send("eth_requestAccounts", []);
   const signer = provider.getSigner();
   const Add = "<Contract Address>";
   const contract = new ethers.Contract(
     Add,
     contractABI,
     signer
   );
   let tx = await contract.writeFoo(params);
   await tx.wait();
}

const foo = async (params) => {
       const provider = new ethers.providers.Web3Provider(window.ethereum);
       await provider.send("eth_requestAccounts", []);
       const Add = "<Contract Address>";
       const contract = new ethers.Contract(
         Add,
         contractABI,
         provider
       );
       let tx = await contract.readFoo(params);
       await tx.wait();
   }

如果您仔細閱讀兩個程式碼片段,您會發現當我嘗試獲取合約實例時,在第一個片段中,我使用了addresscontractABIsigner。在第二個片段中,我使用了addresscontractABIprovider

在您編寫交易時,您需要簽署交易,這就是我通過簽名者的原因(如果您這樣做,metamask 會徵求您的許可)。

而在第二份契約中,我只是在閱讀(readFoo)所以我不必簽署,因此我通過了提供者。使用哪一種完全取決於情況。

告訴我它是否有幫助!

編輯:

這比以前更容易。您所要做的就是在部署之前創建錢包實例並以程式方式登錄。要知道,沒有界面,你必須使用私人地址登錄。

const { ethers } = require("ethers");
require("dotenv").config();

const { GOERLI_PRIVATE_KEY, ALCHEMY_API_KEY } = process.env;

const provider = new ethers.providers.JsonRpcProvider(
 `https://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}`
);

const sender = "0xe515E4883c503584e2DfbdAF60149DAbc123657b";
const receiver = "0x2F600dFC67E8AFDbCb650790c13cB94178871C7B";

const wallet = new ethers.Wallet(GOERLI_PRIVATE_KEY, provider);

const address = "0x326C977E6efc84E512bB9C30f76E30c160eD06FB";

const abi = [
 "function balanceOf(address) view returns(uint)",
 "function transfer(address to, uint amount) returns(bool)",
];

const contract = new ethers.Contract(address, abi, provider);

const main = async () => {
 const senderBefore = await contract.balanceOf(sender);
 const receiverBefore = await contract.balanceOf(receiver);

 console.log(
   `Sender balance before the transfer is: ${ethers.utils.formatEther(
     senderBefore
   )}`
 );

 console.log(
   `Receiver balance before the transfer is: ${ethers.utils.formatUnits(
     receiverBefore,
     "ether"
   )}`
 );

 const amount = ethers.utils.parseEther("5");

 const contractWithWallet = contract.connect(wallet);

 const tx = await contractWithWallet.transfer(receiver, amount);

 await tx.wait();

 console.log(tx);

 const senderAfter = await contract.balanceOf(sender);
 const receiverAfter = await contract.balanceOf(receiver);

 console.log(
   `Sender balance before the transfer is: ${ethers.utils.formatEther(
     senderAfter
   )}`
 );

 console.log(
   `Receiver balance before the transfer is: ${ethers.utils.formatUnits(
     receiverAfter,
     "ether"
   )}`
 );
};

main().catch((error) => {
 console.log(error);
 process.exit(1);
});

這是一個有點大的程式碼,它將回答您的問題。如果您從後端簽名,幾乎沒有什麼會改變。首先,您需要節點提供程序。我在這裡使用了煉金術,您可以使用一種方便。

其次,你需要你的私鑰。在這種情況下,我建議您創建 .env 文件並儲存您的私人地址、alchemy api 等。

因為如果您將應用程序上傳到 github 會更安全,並且您始終可以將 .env 文件添加到 .gitignore 文件以停止推送。

因此,首先要從後端簽名,您使用帶有私鑰和提供者作為參數的 ethers.wallet 方法。

但是,這只是wallet使用您的私人地址創建,但您並沒有真正簽署它。

要簽名,請使用以下方法.connect

const contractWithWallet = contract.connect(wallet);

您使用自定義地址簽名。從現在開始,您可以使用需要使用者登錄的智能合約功能。

在你的情況下:

const tx = await contractWithWallet.sign(abi, rawTransaction, keys);

就是這個。如果你願意,你也可以像這樣傳遞自定義私鑰。

const init = async (PRIVATE_KEY) => {
 const wallet = new ethers.Wallet(`${PRIVATE_KEY}`, provider);

 ......
 // Here you can connect the wallet with the contract and call the 
    function in the contract.
}

編輯2:

在安全帽中,只要您有自定義提供程序 API,您就可以添加任意數量的提供程序。

下面,我分享了我的 hardhat.config.json 文件。在那裡你可以看到我是如何添加多個提供者的。

const {
 GOERLI_PRIVATE_KEY,
 ALCHEMY_API_KEY,
 QUICKNODE_API_KEY,
} = process.env;

module.exports = {
 solidity: "0.8.9",
 networks: {
   goerli: {
     url: `https://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
     accounts: [GOERLI_PRIVATE_KEY],
   },
   bsctest: {
     url: `https://radial-wispy-dinghy.bsc-testnet.discover.quiknode.pro/${QUICKNODE_API_KEY}`,
     accounts: [GOERLI_PRIVATE_KEY],
   },
 },

這就是您為初學者添加提供程序的方式。然後,當您嘗試部署合約時,它將遵循以下步驟。

  1. 寫契約
  2. 在腳本文件夾中創建 deploy.js 文件。
  3. 使用終端部署它。

從根文件夾中,您將執行此命令。

npx hardhat run scripts/deploy.js --network goerli

npx hardhat run scripts.deploy.js --network bsctest

第一個給goerli。您可以提供所需的自定義名稱。第二個用於 bsc 測試網。

您也可以直接從安全帽終端直接驗證合約,而無需使用 etherscan 或 bscscan。看看這個。

安全帽驗證

安全帽入門

安全帽文件

Hardhat 有最好的文件。您可以在那裡找到大多數參考資料。嘗試在那裡尋找深刻的理解。

安全帽定制提供商

教程- 您可以在此處找到大部分有用的教程。

為自定義提供程序功能提供接受原始交易數據的能力,這些數據將在內部使用我們自己的庫進行簽名,然後發送到區塊鏈

無論您的要求是什麼,您都將使用 ether.js 在 deploy.js 文件中執行此操作。您只能使用上面的這些命令進行部署,並且可以使用原始交易數據傳遞給新函式以登錄 javascript 文件。

原始交易

嗯,這就是你要找的嗎?

引用自:https://ethereum.stackexchange.com/questions/137037