체인의정석

ethers에서 원하는 주소로 eip712 서명하기 (테스트 코드가 아닌 이미 존재하는 지갑 주소로 eip712 형태의 서명하는 방법) 본문

블록체인/NFT & BRIDGE

ethers에서 원하는 주소로 eip712 서명하기 (테스트 코드가 아닌 이미 존재하는 지갑 주소로 eip712 형태의 서명하는 방법)

체인의정석 2022. 7. 29. 13:27
728x90
반응형

테스트 코드 작성 이후 실제 메인네트워크에서 잘 작동하나 확인을 하기 위해서 따로 스크립트를 만들어야 했다.

일단 내가 사용하는 환경은 체인별로 설정 값이 다르니 hardhat에서 단위 테스트와 시나리오 테스트를 맞추었다 하더라도 실제로 트랜잭션을 보내보고 검토하는 과정이 필요하다.

 

근데 EIP712를 테스트하는 과정에서 원래는 메타마스크에서 서명 정보를 받은 후 DB에 저장하는 부분이 있는데

DB를 넣고 테스트 할 수 없으니, struct를 만드는 부분은 helper로 타입을 지정하여 따로 구현을 하였다.

 

이런식으로 지정해 두면 makeOrder(구조체 내용)을 넣고 스크립트를 돌릴 수 있다.

 

structHelper.ts

export enum Type {
  A1,
  A2,
}

export type StructA = {
  contractAddress: string;
  type: Type;
  address: string;
  ratio: number;
  id: string;
};

export const makeOrder = (
  _contractAddress: string,
  _type: type,
  _address: string,
  _ratio: number,
  _id: string
) => ({
  contractAddress: _contractAddress,
  type: _type,
  address: _address,
  ratio: _ratio,
  id: _id,
});

아무튼 이런 구조체를 만드는걸 하나 만들어준 후에는 메타마스크에서 받아오는것과 똑같은 signature를 받아오는 과정이 필요하다.

const signerA = ethersProvider.getSigner();

export const msgParamsBuy = {
  domain: {
    // Give a user friendly name to the specific contract you are signing for.
    name: name,
    // Just let's you know the latest version. Definitely make sure the field name is correct.
    version: version,
    // Defining the chain aka Rinkeby testnet or Ethereum Main Net
    chainId: ethers.BigNumber.from(exampleContract.getChainId()).toNumber(),
    // If name isn't enough add verifying contract to make sure you are establishing contracts with the proper entity
    verifyingContract: exampleContract,
  },

  // Defining the message signing data content.
  message: {
    /*
    - Anything you want. Just a JSON Blob that encodes the data you want to send
    - No required fields
    - This is DApp Specific
    - Be as explicit as possible when building out the message schema.
    */
	 contractAddress: "0x1231452314234..",
     type: 0, //A1이라는 뜻
     address: "",
     ratio: 100,
     id: "sdfawefae123"
  },
  // Refers to the keys of the *types* object below.
  primaryType: "Order",
  types: {
    Order: [
      { name: "contractAddress", type: "address" },
      { name: "type", type: "uint8" },
      { name: "address", type: "address" },
      { name: "ratio", type: "uint256" },
      { name: "id", type: "string" },
    ],
  },
};

export const signatureA = signerA._signTypedData(
  msgParamsBuy.domain,
  msgParamsBuy.types,
  msgParamsBuy.message
);

signature의 경우 대략 이런식으로 만들면 된다.

 

근데 이때 signer는 각각 다른 signer를 가져와서 함수를 실행시켜야 한다.

https://docs.ethers.io/v5/api/providers/jsonrpc-provider/

 

JsonRpcProvider

Documentation for ethers, a complete, tiny and simple Ethereum library.

docs.ethers.io

const ethersProvider = new ethers.providers.JsonRpcProvider(
  process.env.RPC_URL
);
const wallet = new Wallet(process.env.SELLER_ADDRESS_PK!, ethersProvider);
const ContractExmaple = new ethers.Contract(
  ContractExmapleAddress,
  ContractExmapleABI,
  wallet
);

signerA = ethersProvider.getSigner();

그러나 위와 같이 getSigner를 하면 원하는 사인이 되지 않앗다.

 

방법은 아래 코드에서 찾아볼 수 있었다.

https://github.com/ethers-io/ethers.js/discussions/2835

 

Ether js signedTypeData & metamask sig utils signedTypeData_v4 producing different signature · Discussion #2835 · ethers-io/et

import { signTypedData, } from "@metamask/eth-sig-util"; import { ethers } from "ethers"; const domain = { name: "name", // contract deploy name version: "1"...

github.com

const walletForSign = new ethers.Wallet(process.env.A_ADDRESS_PK!);

async function signTypedData() {
  await walletForSign
    ._signTypedData(
      msgParams.domain,
      msgParams.types,
      msgParams.message
    )
    .then((signature) => {
      console.log("signature >>>>", signature);
    });
}

signTypedData();

이런식으로 wallet을 만들어 준 후에 안에 동기처리를 해주는 식으로 값을 도출 할 수 있었다.

 

signature 위에다가 let으로 변수를 선언해 주고 .then안에 signature를 정의해준 결과 결국 메타마스크에서 사인한 값을 가져와서 넣을 수 있게 되었다.

728x90
반응형
Comments