BlockChain - gas paymaster, meta transaction, ethers
목차
1. ERC 4337
2. 계정 추상화
3. ERC4337 이전에 제안된 개념
4. 가스비 대납 paymaster
5. metaTransaction 실습
6. ethers 사용하기
1. ERC 4337
① user Operations
- 프론트 페이지에서 보내는 객체(트랜잭션 형태)
- 새로운 트랜잭션 pool에 요청하면 객체가 쌓임(pending상태)
- EIP-2718 === 미래의 거래유형을 위해서 새로운 트랜잭션 pool 유형을 정의함
- 기존의 트랜잭션 수정하기 않기 위해서 → 이전버전과 호환이 되지않을수있기때문
- Dapp 환경에서 새로운 트랜잭션 풀에 담기위해 새로운 객체를 만들어서 요청을 보냄,
→ 담아놓은것을 처리하는것이 bundlers
② bundlers
- user Operations 객체들을 pool에서 수집 → 다중의 서명을 검증 → DTO 데이터를 하나의 트랜잭션 형태로 변경함
→ 컨트랙트로 요청보냄
- node에서 배웠던 entity라고 생각하기
- 객체들을 다 가지고 와서 서명을 검증하는 암호학을 추가할수도있음
③ entrypoint
- bundlers에서 보낸 트랜잭션 내용을 처리할 컨트랙트
- ERC 4337 사용 목적
→ WEB3의 지식이없는 유저도 일반페이지/앱 사용하는 느낌을 받게 UX 경험을 좋게 만들어주기 위해
2. 계정 추상화
- 추상화의 개념은 실제의 것에서 시작해서 불필요한 요소들을 제거함
- 계정에는 EOA, CA 가 있는데 이 두개를 모호하게 만들어
- CA를 EOA처럼 사용해서 더 복잡한 트랙잭션 요청하는것
- 기존의 방식은 EOA계정이 개인키로 서명해서 트랜잭션을 CA에 요청하는 차이가 있음
- EOA, CA는 개인키 유무차이가 있음 (CA는 개인키 X)
- 계정을 추상화 한다는 것은 EOA와 CA 두계정 모두 트랜잭션 발생가능하게 함 -> EOA와 CA의 차이를 줄임
- 추상화하려는 이유 :
- EOA계정을 사용자가 직접 가지고 사용하지 않음!
- CA계정을 하나 만들어주어서 CA계정으로 요청을 보낼수있게 로직을 작성
- 다중 서명 확인과 임의의 서명 확인(암호학)
- 일정 시간 출금 불가능, 소셜 복구
- 사용자는 클릭 한번으로 web3 생태계에 참여가 가능해짐
- 추상 계정의 단점 보완으로 서명의 문제 : EIP-1271 방식으로 서명하는데 추상계정은 다른 방식의 서명을 사용해야해서 가스비를 연구해서 제안한 내용
3. ERC4337 이전에 제안된 개념
- EIP 이더리움 개선 제안
- https://eips.ethereum.org/EIPS/eip-4337
- EIP 중에서 EIP-86, EIP-2938 실현이 불가능했고
- 합의계층을 변경하지 않고 상위 인프라에서 계정을 추상화하는 접근 방식을 도입
- ERC4337은 CA의 컨트랙트를 사용자가 계정으로 사용할수있게 검증 로직을 작성하는 개념
- 이더리움 합의계층의 변경을 피하고 상위 인프라에서 해결
- 기존의 이더리움 프로토콜을 추가나 트랜잭션 구조를 변경하지 않고 추상화 시키자는 것
- user Operations의 객체 내용을 새로운 트랜잭션 풀에 담고
- 각각의 노드는 bundlers를 통해 user Operations의 객체들을 조회해서 하나의 트랜잭션으로 엔트리포인트(컨트랙트)에 요청을 보낸다.
4. 가스비 대납 paymaster
- 번들러에서 엔트리포인트과정에서 가스비를 대납해주는 metaTransaction
- web3를 모르는 사용자의 경우 가스비를 모르고,
- 웹사이트에서 토큰을 받아 수가 늘어나고 그 토큰을 사용하고자할때 가스비가 없어서 토큰을 지불할수가 없음
(트랜잭션을 발생시킬수가없음)
- 이런 사용자를 위해 가스비를 대신 지불해주는 대신 나중에 다른형태로 요금발생시키는 것
(이후 어떻게 요금 발생시킬지는 우리가 작성할 로직내용)
5. metaTransaction 실습
- 설치하기
npx create-react-app meta
npm install ethers ganache express cors axios @openzeppelin/contracts
npx ganache
remixd -s . --remix-ide "https://remix.ethereum.org/"
- 가나쉬 네트워크 사용해서 제공하는 10개의 계정 사용 (그중에 가장 마지막 지갑을 대납 역할 계정)
- ERC20 토큰을 민트하는 컨트랙트작성 (token.sol, metaTransactiosn.sol)
- express 백엔드열고 api설정, axois로 요청
- remix로 배포하기
- 가장 마지막 계정으로 배포하기
- 토큰먼저 배포하고 그 트랜잭션 CA계정으로 metatransaction 배포
- 다시 서버로 돌아가서 app.post('/metaTransaction') 작성
- 객체를 트랜잭션 pool에 담아놓고 서명검증하기
- 백엔드 다중 트랜잭션 처리하면서 가스비를 가장 마지막 계정이 지불
6. ethers 사용하기
https://docs.ethers.org/v6/getting-started/
** 기존방식으로 확장프로그램 연결하는 방법
- getSigner() : 접속된 계정확인 가능함
- getBalance() : 연결된 지갑의 잔액
- formatEther() : 이더단위로 변경
*** 가나쉬 네트워크 계정전체를 객체로 담아서 사용하는방법
- ganache 사용하기 Private Keys 전체를 객체에 담아 사용
- JsonRpcProvider() : 경로를담아 "http://127.0.0.1:8545" 요청 → 가나쉬
- 여러개의 비동기를 처리하기위해 promise.all사용
- Wallet() : 지갑이 해당 네트워크에 요청 보낼수있는 인스턴스 생성
- wallet.address : 개인키로 만든 공개키
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider('http://127.0.0.1:8545');
const wallet = new ethers.Wallet(myPrikey, provider);
const balance = await provider.getBalance(wallet);
const balanceETH = ethers.formatEther(balance);
const senderSigner = ethers.verifyMessage(JSON.stringify(message), signature);
const contract = new ethers.Contract(contractAddress, contractABI, provider);
const ethPrv = new ethers.BrowserProvider(window.ethereum);
const signer = await ethPrv.getSigner();
※ user Operations으로 객체를 만들고 그걸 트랜잭션 POOL에 담고 bundlers에서 객체를 트랜잭션으로 만들어서 엔트리포인트(컨트랙트)에 요청을 보낸다!
※ EIP(Ethereum Improvement Proposals) 이더리움 개선 제안 제도
※ EIP 2771 (가스 리스 대납) : 기존 트랜잭션의 구조를 유지하면서 상위의 트랜잭션의 풀을 하나 더 만들어 관리하는 것