체인의정석

hardhat, ethers 테스트 코드 스크립트로 바꾸는 법 (여러 지갑주소로 서명하는 스크립트 만드는법) 본문

블록체인/Ethers & web3

hardhat, ethers 테스트 코드 스크립트로 바꾸는 법 (여러 지갑주소로 서명하는 스크립트 만드는법)

체인의정석 2023. 3. 11. 12:18
728x90
반응형

그동안 테스트 코드에서만 여러 지갑 주소를 사용하다가

스크립트에 직접 사용하면 어떻게 해야 할지 찾아봤다.

 

먼저 config에 프라이빗 키를 배열 형태로 설정해준다.

    goerli: {
      url: process.env.RPC_URL,
      accounts: [process.env.PRIVATE_KEY!, process.env.TEST_PRIVATE_KEY!]
    },
    matic: {
      url: process.env.RPC_URL_MATIC,
      accounts: [process.env.PRIVATE_KEY!, process.env.TEST_PRIVATE_KEY!]
    },
    bsc: {
      url: process.env.RPC_URL_BSC,
      accounts: [process.env.PRIVATE_KEY!, process.env.TEST_PRIVATE_KEY!]    
    },
    klaytn: {
      url: process.env.RPC_URL_KLAYTN,
      accounts: [process.env.PRIVATE_KEY!, process.env.TEST_PRIVATE_KEY!]
    }

이렇게 되고 나면 

import { ethers } from "hardhat";

async function main() {
  const accounts = await ethers.getSigners();

  for (const account of accounts) {
    console.log("account >>", account.address)
  }
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

이렇게 스크립트를 만들게 되면  이를 이용해서 여러 지갑주소로 서명하는 실제 네트워크의 서명 스크립트를 만들 수 있습니다.

hyunkicho@Hyunkiui-MacBookPro tutorial_hardhat % npx hardhat run scripts/getSinger.ts --network bsc  
account >> 0x3F8bE5375B82390d09E3fF60835eafb162bfeDcc
account >> 0x8Ce636aF0417a1d368FE9e36eC8c7B91cBAD517e

요런 식으로 주소들이 나오게 되고

address를 뺀 다음에 connect를 쓰면 실제로 함수가 실행되게 된다.

그럼 테스트코드를 실제 스크립트로 이식해보겠다.

먼저 테스트코드는

import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { EtherStore } from '../typechain-types/contracts/EtherStore.sol/EtherStore';
import { Contract } from 'ethers';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';

describe("etherStore", function () {
  // We define a fixture to reuse the same setup in every test.
  // We use loadFixture to run this setup once, snapshot that state,
  // and reset Hardhat Network to that snapshot in every test.
  let etherStore: Contract;
  let attack: Contract
  let eve: SignerWithAddress;
  let alice: SignerWithAddress;
  let bob: SignerWithAddress;
  let owner: SignerWithAddress;

  describe("etherStore", function () {
    it("Deposit 1 Ether each from Account 1 (Alice) and Account 2 (Bob) into etherStore", async function () {
      [owner, alice, bob, eve] = await ethers.getSigners();

      const EtherStore = await ethers.getContractFactory("EtherStore");
      etherStore = await EtherStore.deploy();
      const Attack = await ethers.getContractFactory("Attack");
      attack = await Attack.deploy(etherStore.address);
      await etherStore.connect(alice).deposit({value: (1*(10**18)).toString()});
      await etherStore.connect(bob).deposit({value: (1*(10**18)).toString()});
      console.log("etherStore balance : ", await ethers.provider.getBalance(etherStore.address))
    });

    it("Call Attack.attack sending 1 ether (using Account 3 (Eve))", async function () {
      console.log("before sending1 eth : ", await attack.getBalance());
      console.log("before sending1 eth attack: ", await ethers.provider.getBalance(attack.address))
      console.log("before sending1 eth eve : ", await ethers.provider.getBalance(eve.address))
      console.log("etherStore balance etherStore: ", await ethers.provider.getBalance(etherStore.address))

      attack.connect(eve).attack({value: (1*(10**18)).toString()})

      console.log("after sending1 eth : ", await attack.getBalance());
      console.log("after sending1 eth : attack ", await ethers.provider.getBalance(attack.address))
      console.log("after sending1 eth : eve ", await ethers.provider.getBalance(eve.address))
      console.log("etherStore balance : etherStore", await ethers.provider.getBalance(etherStore.address))
    });
  });
});

요 부분이다. 재진입 공격 테스트코드이다.

 

이를 스크립트로 바꾸면

import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { EtherStore } from '../typechain-types/contracts/EtherStore.sol/EtherStore';
import { Contract } from 'ethers';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';

describe("etherStore", function () {
  // We define a fixture to reuse the same setup in every test.
  // We use loadFixture to run this setup once, snapshot that state,
  // and reset Hardhat Network to that snapshot in every test.
  let etherStore: Contract;
  let attack: Contract
  let eve: SignerWithAddress;
  let alice: SignerWithAddress;
  let bob: SignerWithAddress;
  let owner: SignerWithAddress;

  describe("etherStore", function () {
    it("Deposit 1 Ether each from Account 1 (Alice) and Account 2 (Bob) into etherStore", async function () {
      [owner, alice, bob, eve] = await ethers.getSigners();

      const EtherStore = await ethers.getContractFactory("EtherStore");
      etherStore = await EtherStore.deploy();
      const Attack = await ethers.getContractFactory("Attack");
      attack = await Attack.deploy(etherStore.address);
      await etherStore.connect(alice).deposit({value: (1*(10**18)).toString()});
      await etherStore.connect(bob).deposit({value: (1*(10**18)).toString()});
      console.log("etherStore balance : ", await ethers.provider.getBalance(etherStore.address))
    });

    it("Call Attack.attack sending 1 ether (using Account 3 (Eve))", async function () {
      console.log("before sending1 eth : ", await attack.getBalance());
      console.log("before sending1 eth attack: ", await ethers.provider.getBalance(attack.address))
      console.log("before sending1 eth eve : ", await ethers.provider.getBalance(eve.address))
      console.log("etherStore balance etherStore: ", await ethers.provider.getBalance(etherStore.address))

      attack.connect(eve).attack({value: (1*(10**18)).toString()})

      console.log("after sending1 eth : ", await attack.getBalance());
      console.log("after sending1 eth : attack ", await ethers.provider.getBalance(attack.address))
      console.log("after sending1 eth : eve ", await ethers.provider.getBalance(eve.address))
      console.log("etherStore balance : etherStore", await ethers.provider.getBalance(etherStore.address))
    });
  });
});

이렇게 되고 그에 따른 결과는

hyunkicho@Hyunkiui-MacBookPro tutorial_hardhat % npx hardhat run scripts/deposit.ts --network local
etherStore balance :  BigNumber { value: "2000000000000000000" }
before sending1 eth :  BigNumber { value: "0" }
before sending1 eth attack:  BigNumber { value: "0" }
before sending1 eth eve :  BigNumber { value: "100000000000000000000" }
etherStore balance etherStore:  BigNumber { value: "2000000000000000000" }
after sending1 eth :  BigNumber { value: "0" }
after sending1 eth : attack  BigNumber { value: "0" }
after sending1 eth : eve  BigNumber { value: "98998550680000000000" }
etherStore balance : etherStore BigNumber { value: "0" }
hyunkicho@Hyunkiui-MacBookPro tutorial_hardhat % npx hardhat run scripts/deposit.ts --network klaytn
etherStore balance :  BigNumber { value: "2000000000000000000" }
before sending1 eth :  BigNumber { value: "0" }
before sending1 eth attack:  BigNumber { value: "0" }
before sending1 eth eve :  BigNumber { value: "99999475000000000000" }
etherStore balance etherStore:  BigNumber { value: "2000000000000000000" }
after sending1 eth :  BigNumber { value: "0" }
after sending1 eth : attack  BigNumber { value: "0" }
after sending1 eth : eve  BigNumber { value: "99999475000000000000" }
etherStore balance : etherStore BigNumber { value: "2000000000000000000" }

https://baobab.scope.klaytn.com/tx/0x94691fa4f8e79199cce142ec98680dfe52a7be68770faf03790fbd1f41b8069c?tabId=internalTx 

 

Klaytnscope

Klaytnscope allows you to find data by monitoring network health and statistics of Klaytn as well as profiling blocks and transactions on Klaytn.

baobab.scope.klaytn.com

 

 

결과가 잘 나왔습니다.

 

테스트 코드가 이상해서 다시 한건데 그 이유는 이더리움 잔고의 경우 업데이트를 하고 다음 블록에서 조회를 해야 조회가 되는것 같습니다.

728x90
반응형
Comments