본문으로 건너뛰기
0%

User operation이란?

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

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

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

Embedded Accounts와 account abstraction 인프라를 사용하여 새로운 사용자가 이메일 및 패스키로 임베디드 지갑을 생성할 수 있도록 하세요!

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

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

유저 오퍼레이션(UOs)에는 일반 트랜잭션과 유사한 필드(예: sender, to, calldata, maxFeePerGas, maxPriorityFee, signature, nonce)가 포함되어 있지만, callGasLimit, verificationGasLimit, preVerificationGas, paymasterAndData와 같이 유저 오퍼레이션 구조체에만 존재하는 새로운 필드도 포함하고 있습니다.

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

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

유저 오퍼레이션의 설계 및 아키텍처에 대한 설명은 Alchemy의 AA infra 팀 엔지니어인 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 paymaster처럼 유저 op의 내용에 의존하지 않는 paymaster를 사용하는 경우, 이 단계에서 paymasterAndData를 채울 수 있습니다.
  5. 오퍼레이션에 필요한 가스 수수료를 추정하고 maxFeePerGas와 maxPriorityFeePerGas를 채웁니다
  6. (선택 사항) 서명을 위해 유저 op를 스폰서 paymaster에게 전송하고 paymasterAndData를 채웁니다
  7. paymaster의 서명은 위의 모든 필드가 채워져 있어야 하므로 이 단계에서 수행해야 합니다.
  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 signer와 provider도 지원합니다.

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

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

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

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

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

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

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

1. 유저 op의 유효성 검사

초기 일련의 검사는 ERC-4337 명세의 "UserOperation을 수신했을 때의 Client 동작" 섹션에 설명되어 있으며, 아래에 요약되어 있습니다:

  • 발신자가 기존 컨트랙트이거나, (컨트랙트를 생성하는 데 사용되는) initCode가 비어 있지 않아야 합니다(하지만 둘 다일 수는 없습니다)
  • initCode가 비어 있지 않은 경우(유저 op가 계정을 생성하기 때문에), factory가 스테이크되어 있는지 여부를 확인합니다
  • verificationGasLimit이 충분히 낮아야 합니다(MAX_VERIFICATION_GAS 이하)
  • preVerificationGas가 calldata 가스 및 오버헤드 가스 수수료를 지불하기에 충분히 높아야 합니다
  • paymasterAndData는 비어 있거나 paymaster 주소로 시작해야 합니다
  • paymaster가 존재하는 경우, 온체인에 비어 있지 않은 코드가 있어야 하고, 유저 op 비용을 지불할 자금이 있어야 하며, 밴 당하지 않아야 합니다
  • callgas는 최소한 값이 있는 CALL의 비용 이상이어야 합니다
  • maxFeePerGasmaxPriorityFeePerGas는 client가 수락할 최소값 이상이어야 합니다
  • 발신자는 풀에 다른 유저 op를 가지고 있지 않아야 합니다(또는 기존 항목을 대체하도록 유저 op가 구성되어야 합니다)

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

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

2. 유저 오퍼레이션 시뮬레이션

유저 op가 이러한 기본 검사를 통과하면, client는 유저 op가 자체 자금으로든 paymaster를 사용해서든 자신의 실행 비용을 지불할 수 있는지 검증하기 위해 유저 오퍼레이션을 시뮬레이션해야 합니다.

유저 op를 시뮬레이션하기 위해, Bundler는 simulateValidation() 메서드를 호출하며, 이 메서드는 발신자의 계정에서 validateUserOp 함수를 호출하거나, paymaster가 유저 op 실행을 위한 가스 수수료를 스폰서할 경우 paymaster의 컨트랙트 계정에서 validatePaymasterUserOp를 호출합니다.

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

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

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

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

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

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

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

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

*모든 검증이 먼저 실행되고, 그 후에야 검증된 유저 op에 대한 모든 실행이 실행됩니다.

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

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

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

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

Background gradient

블록체인 매직을 만드세요

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