본문으로 건너뛰기
0%

User Operation란 무엇인가요?

2023년 6월 26일에 게시됨4분 읽기

유저 오퍼레이션은 발신자의 스마트 컨트랙트 계정을 대신해 실행될 트랜잭션 세부 정보를 담은 객체입니다. 유저 오퍼레이션은 ERC-4337을 지원하는 Ethereum 및 레이어 2 블록체인에서 컨센서스 레이어 변경 없이 Account Abstraction이 작동할 수 있도록 하는 의사 트랜잭션 객체입니다.

스마트 컨트랙트 지갑(SCW)을 개발하거나 탈중앙화 애플리케이션을 SCW와 호환되도록 만들려면, 유저 오퍼레이션을 정의하는 파라미터, 유저 op 구성 과정에서 유저 op 필드가 채워지는 방식, 유저 op가 Bundler에 의해 번들링되는 방식, 그리고 페이마스터에 의해 검증 및 실행되는 방식을 이해하는 것이 도움이 됩니다.

Embedded Accounts와 account abstraction 인프라를 사용해 신규 사용자를 위한 이메일 및 패스키 임베디드 지갑 생성을 지원하세요!

시청: Solidity로 유저 오퍼레이션 빌드 및 실행하기

유저 오퍼레이션에 포함된 필드는 무엇인가요?

유저 오퍼레이션(UO)은 일반 트랜잭션과 유사한 필드(예: sender, to, calldata, maxFeePerGas, maxPriorityFee, signature, nonce)를 포함하지만, callGasLimit, verificationGasLimit, preVerificationGas, paymasterAndData와 같이 유저 오퍼레이션 구조체에만 특화된 새로운 필드도 포함합니다.

UO 필드에 대한 정의는 공식 ERC-4337 명세에서 확인할 수 있습니다. 여기에 요약되어 있습니다:

  • callGasLimit - 메인 실행 호출에 사용될 가스
  • verificationGasLimit - 검증 단계를 완료하는 데 사용될 가스
  • preVerificationGas - 사전 검증 실행 및 calldata 비용을 충당하기 위해 Bundler에게 지불할 가스
  • paymasterAndData - 스폰서링 페이마스터의 주소와 페이마스터에 전달할 데이터

유저 오퍼레이션의 설계와 아키텍처에 대한 설명은 Alchemy의 AA 인프라 팀 엔지니어인 David Philipson이 작성한 "You Could Invented Account Abstraction" 시리즈 1부에서 읽을 수 있습니다.

다음으로, 유저 오퍼레이션의 필드를 올바르게 채우기 위한 표준 워크플로우를 알아보겠습니다.

유저 오퍼레이션을 전송하는 흐름은 어떻게 되나요?

Bundler에 유저 오퍼레이션(유저 op)을 전송하는 일반적인 흐름은 여러 단계로 구성됩니다:

  1. sender, nonce, initCode, callData가 채워진 부분 유저 op를 구성합니다
  2. eth_estimateUserOperationGas를 통해 Bundler RPC에 부분 유저 op의 가스를 추정합니다
  3. preVerificationGas, verificationGasLimit, callGasLimit을 채웁니다
  4. ERC20 페이마스터처럼 유저 op의 내용에 의존하지 않는 페이마스터를 사용하는 경우, 이 단계에서 paymasterAndData를 채울 수 있습니다.
  5. 오퍼레이션에 필요한 가스 요금을 추정하고 maxFeePerGas와 maxPriorityFeePerGas를 채웁니다
  6. (선택 사항) 서명을 위해 스폰서링 페이마스터에 유저 op를 전송하고 paymasterAndData를 채웁니다
  7. 페이마스터의 서명은 위의 모든 필드가 채워져 있어야 하므로 이 단계에서 반드시 수행해야 합니다.
  8. 유저 op에 서명하고, signature를 채운 후, eth_sendUserOperation을 통해 Bundler에 유저 op를 전송합니다

개발자는 네이티브 ethers.js를 사용해 각 유저 오퍼레이션 필드의 값을 얻을 수 있지만, UO 구성을 더 쉽게 만들어주는 몇 가지 web3 개발자 도구가 있습니다.

개발자가 유저 오퍼레이션을 구성하는 데 사용할 수 있는 도구는 무엇인가요?

Alchemy의 오픈소스 AA SDK와 같은 유저 오퍼레이션 구성 도구는 네이티브 ethers.js로 유저 op를 만드는 것보다 유저 오퍼레이션 빌드를 더 쉽게 만들어줍니다.

Alchemy의 AA SDK

Alchemy의 AA SDK는 viem으로 구축되어 개발자에게 경량 번들을 제공합니다. GitHub의 aa-sdk는 aa-ethers 라이브러리를 통해 ethers.js 서명자와 provider도 지원합니다.

aa-sdk를 사용해 유저 오퍼레이션을 구성할 때의 주요 이점 중 하나는 두 가지 유틸리티 메서드입니다:

  1. sendUserOperation - 가스 추정, paymasterAndData 요청, 서명 등을 처리합니다
  2. sendTransaction - 트랜잭션 객체 데이터(from, to, data, value)를 유저 오퍼레이션으로 변환합니다

유저 오퍼레이션을 구성하는 작업 순서는 복잡한데, Alchemy의 AA-SDK는 getDummyPaymasterData로 시작해 estimateGas로 가스를 추정하고, 그다음 getFeeData, 마지막으로 getPaymasterAndData를 실행하는 작업 스택을 통해 UO 구성을 단순화합니다.

유저 op 필드의 값을 얻은 후, target, callData, 그리고 선택적인 value를 사용해 유저 오퍼레이션을 빌드하고 서명합니다. 그런 다음 Bundler에 유저 op를 전송하고 유저 op의 해시를 받습니다.

Alchemy의 페이마스터나 별도의 페이마스터를 사용하려는 경우, 또는 자체 SmartAccounts에 대한 지원을 추가할 계획이라면, UO를 쉽게 생성하는 방법에 대한 전체 설명은 Alchemy AA SDK 문서를 참고하세요.

유저 오퍼레이션은 어떻게 유저 op 멤풀에 추가되나요?

유저 op가 멤풀에 추가되기 전에, ERC-4337 명세에 명시된 예상 동작을 따르는지 확인하기 위한 일련의 검사를 통과해야 합니다. 유저 op는 또한 유효하며 자신의 가스 비용을 지불할 수 있는지(발신자의 지갑 또는 페이마스터 스폰서십 정책을 통해) 확인하는 검증 시뮬레이션 검사도 통과해야 합니다.

1. 유저 op의 유효성이 검사됩니다

초기 일련의 검사는 ERC-4337 명세의 "Client behavior upon receiving a UserOperation" 섹션에 설명되어 있으며, 아래에 요약되어 있습니다:

  • 발신자가 기존 컨트랙트이거나, (컨트랙트를 생성하는 데 사용되는) initCode가 비어 있지 않아야 합니다(둘 다는 아님)
  • initCode가 비어 있지 않은 경우(유저 op가 계정을 생성하기 때문에), 팩토리가 스테이킹되어 있는지 여부를 판단합니다
  • verificationGasLimit이 충분히 낮아야 합니다(MAX_VERIFICATION_GAS 이하)
  • preVerificationGas가 calldata 가스와 오버헤드 가스 요금을 지불하기에 충분히 높아야 합니다
  • paymasterAndData는 비어 있거나 페이마스터 주소로 시작해야 합니다
  • 페이마스터가 존재하는 경우, 온체인에 비어 있지 않은 코드가 있어야 하고, 유저 op를 지불할 자금이 있어야 하며, 금지되지 않아야 합니다
  • callgas는 최소한 0이 아닌 값을 가진 CALL의 비용이어야 합니다
  • maxFeePerGas와 maxPriorityFeePerGas는 클라이언트가 수용할 최소값보다 높아야 합니다
  • 발신자는 풀에 다른 유저 op를 가지고 있지 않아야 합니다(또는 유저 op가 기존 항목을 대체하도록 구성되어야 합니다)

이 검사에 영향을 줄 수 있는 여러 규칙이 있으며, 이는 명세에 자세히 설명되어 있습니다.

이 유저 오퍼레이션 소개에서는 유저 op의 유효성을 판단하기 위해 수행되는 상위 수준의 검사만 전달하고자 합니다.

2. 유저 오퍼레이션이 시뮬레이션됩니다

유저 op가 이러한 기본 검사를 통과하면, 클라이언트는 유저 op가 자체 자금을 사용하거나 페이마스터를 사용해 실행 비용을 지불할 수 있는지 검증하기 위해 유저 오퍼레이션을 시뮬레이션해야 합니다.

유저 op를 시뮬레이션하기 위해, Bundler는 simulateValidation() 메서드를 호출하고, 이 메서드는 발신자 계정의 validateUserOp 함수를 호출하거나, 페이마스터가 유저 op 실행에 필요한 가스 요금을 지원하는 경우 페이마스터 컨트랙트 계정의 validatePaymasterUserOp를 호출합니다.

simulateValidation() 메서드가 호출된 후, ValidationResult 응답과 함께 되돌려집니다(revert). 이 함수가 되돌려지는 것은 의도된 동작이며, 이는 성공적인 결과로 간주됩니다.

ValidationResult가 다른 오류와 함께 되돌려지면, 유저 op는 검증 시뮬레이션을 통과하지 못한 것이며 멤풀에 추가되지 않습니다. 유저 op가 sigFail을 반환하면 멤풀에서 제외되며, validUntil 응답이 만료되는 경우에도 UO가 멤풀에서 제외될 수 있습니다.

참고: 유저 op에 initCode가 존재하는 경우, 계정 팩토리가 계정을 생성한 다음, 새로 생성된 계정을 사용해 시뮬레이션 과정이 진행됩니다.

이제 유저 오퍼레이션이 구성, 검사, 시뮬레이션되어 멤풀에 추가되었으므로, 검증 및 실행을 위해 엔트리 포인트 컨트랙트로 전송될 수 있습니다!

유저 오퍼레이션은 어떻게 검증되고 실행되나요?

유저 오퍼레이션 내부의 트랜잭션 세부 정보가 온체인에 게시되려면, 엔트리 포인트 컨트랙트가 유저 오퍼레이션을 검증해야 하며, UO가 검증을 통과하면 엔트리 포인트 컨트랙트가 트랜잭션을 실행한 후 Bundler에게 가스 요금을 상환합니다.

유저 op 검증 및 실행의 기본 단계는 다음과 같습니다:

  1. Bundler는 handleOps() 메서드를 통해 유저 op를 싱글톤 엔트리 포인트 컨트랙트로 전송합니다
  2. 각 op에 대해, 엔트리 포인트는 해당 op의 발신자 지갑에서 validateOp를 호출합니다*
  3. 검증 단계를 통과하지 못한 op가 있으면 폐기됩니다
  4. 다음으로, 각 op의 발신자 지갑에서 executeOp를 호출하여, 사용된 가스량을 추적합니다
  5. 각 op를 실행하는 데 사용된 가스를 지불하기 위해 발신자의 지갑 또는 페이마스터에서 Bundler로 ETH를 전송합니다

*모든 검증이 실행된 후에만 검증된 유저 op에 대한 모든 실행이 실행됩니다.

다음은 엔트리 포인트 컨트랙트가 발신자의 스마트 컨트랙트 지갑을 대신해 유저 오퍼레이션을 검증하고 실행하는 방식을 보여주는 다이어그램입니다:

사용자 작업이 검증되고 실행되는 방식

유저 오퍼레이션은 스마트 컨트랙트 지갑이 Ethereum 및 동등한 L2에서 사용자의 기본 지갑 역할을 할 수 있게 하는 의사 트랜잭션 객체입니다. 스마트 컨트랙트 지갑은 블록체인을 더 접근하기 쉽게 만드는 web3 UX 이점을 도입하며, 이는 Ethereum 및 L2의 AA 인프라 제공업체를 통해 가능해집니다.

여러분의 web3 제품이 스마트 컨트랙트 지갑을 지원한다면, Gas Manager API와 Bundler API를 포함해 Ethereum, Polygon, Arbitrum, Optimism 및 Sepolia와 같은 인기 있는 테스트넷을 위한 Alchemy의 AA 인프라를 살펴보세요!

Background gradient

블록체인 매직을 만드세요

Alchemy는 가장 강력한 Web3 개발자 제품 및 도구를 리소스, 커뮤니티, 그리고 전설적인 지원과 결합합니다.