L2 및 서명 집계자를 위한 ERC-4337 가스 추정
작성자: Dan Coombs, David Philipson
ERC-4337 Gas Estimation에서는 ERC-4337에서 gas가 어떻게 동작하는지, 그리고 저희의 gas 추정 방식에 대해 다뤘습니다. 2부인 Dummy Signatures and Gas Token Transfers에서는 gas 추정이 항상 단순하지만은 않으며 몇 가지 엣지 케이스를 고려해야 한다는 것을 알아봤습니다. 이번 글에서는 저희가 마주친 엣지 케이스 몇 가지를 더 살펴보겠습니다.
L2 문제
Ethereum Layer 2 rollup의 정의 중 하나는 "layer 1이 보안, 데이터 가용성, 탈중앙화를 담당하고, layer 2가 확장성을 담당하도록 한다"는 것입니다.
이를 달성하기 위해 L2는 많은 트랜잭션을 하나의 배치로 "롤업"한 다음 layer 1 블록체인에 게시합니다. 이 트랜잭션 비용은 무료가 아닌데, L1 체인에 대량의 데이터 배치를 게시할 때 발생하는 calldata 비용을 L2가 부담해야 하기 때문입니다.
L2는 이렇게 발생하는 L1 calldata 비용을 사용자에게 청구할 방법이 필요합니다. rollup 프레임워크마다 이를 구현하는 방식이 다릅니다.
이 글에서는 가장 규모가 큰 두 개의 EVM rollup인 Arbitrum과 Optimism에 초점을 맞춥니다.
Arbitrum은 L1 gas 비용을 충당하기 위한 비용을 어떻게 계산할까?
Arbitrum에서는 L1 gas 비용을 충당하기 위한 L2 gas 부과액이 다음 공식으로 계산되며, 여기서 데이터 크기는 Brotli 압축 후의 바이트 크기입니다:
💡 L1 Cost (L1C) = L1 price per byte of data (L1P) * Size of data to be posted in bytes (L1S)
💡 Gas (G) = L1 Cost (L1C) / L2 Gas Price (P)
이 gas는 트랜잭션 실행이 시작되기 전에 부과되며 트랜잭션의 gasLimit에 포함됩니다. 따라서 트랜잭션 gas 추정 시 이를 반영해야 합니다.
Optimism은 L1 gas 비용을 충당하기 위한 비용을 어떻게 계산할까?
Optimism에서도 L1 gas 비용은 비슷한 방식으로 계산되는데, 압축 후 바이트 크기에 L1 fee를 곱합니다. Arbitrum처럼 이 값을 L2 gas로 환산하는 대신, Optimism은 필요한 ETH를 sender의 계정에서 직접 차감합니다.
Sender는 gas 추정 시 이 값을 고려할 필요가 없지만, 지출에 대한 한도를 설정할 수도 없습니다. Optimism은 이 fee가 급등하지 않도록 관리합니다.
L2에서 bundler는 L1 fee를 어떻게 청구할 수 있을까?
두 경우 모두 L2에서 bundle 트랜잭션을 제출하는 bundler가 L1 fee를 부담하게 됩니다. bundler는 L2 gas를 늘려서 bundle된 user operation들에게 이 fee를 청구할 방법이 필요합니다.
L2 gas에 미치는 실질적인 영향은 다음과 같이 계산할 수 있습니다:
L2\_gas = L1\_gas \* L1\_fee / L2\_fee
verificationGasLimit와 callGasLimit은 entry point에 의해 계측되므로 bundler가 이 추가 gas를 청구하는 데 사용할 수 없습니다. bundler는 다른 방법에 의존해야 합니다.
시도 1: 더 높은 priority fee 설정
더 높은 maxPriorityFeePerGas를 요구하면 bundler가 이렇게 손실된 fee를 회수할 수 있을지도 모릅니다.
계산 방식은 다음과 같습니다:
- L1 fee를 추정하고 L2 gas로 환산합니다 a. user operation 1개 크기의 bundle을 가정하고, 일반적으로 특수 contract call 형태로 노출되는 네트워크 제공 메서드를 사용해 gas를 추정합니다. b. 이 fee를 L2 gas 값으로 환산하려면 L1 base fee와 L2 base fee를 모두 가정해야 합니다.
verificationGasLimit를 추정합니다 a. 이 gas limit은 엄격한 simulation 규칙 하에 있으므로,callGasLimit과 달리 추정 값이 실제 값에 매우 근접할 가능성이 높습니다.maxPriorityFeePerGasBuffer=L1\_fee / verificationGasLimit로 설정합니다- 필요한 priority fee에 그 buffer를 더합니다
이 방식이 동작할 수는 있지만, UX가 매우 나쁩니다.
자신을 보호하기 위해 bundler는 사용될 call gas 양이 0이라고 가정하고, verification gas만이 유일한 구성 요소인 것처럼 사용자에게 청구해야 합니다. 그러면 사용자는 사용된 call gas 양에 buffer priority fee 구성 요소를 곱한 만큼 과다 지불하게 됩니다. 이는 사용자에게 좋지 않습니다.
시도 2: preVerificationGas 조작
그렇다면 조작할 만한 합리적인 필드는 preVerificationGas뿐입니다. 이는 앞서 제시한 preVerificationGas의 정의, 즉 "entry point가 측정할 수 없는 모든 gas 사용량을 포착하기 위한 gas 필드"라는 정의와 잘 맞습니다. entry point가 계측하지 않는 gas이므로, 이 필드를 사용해 사용자에게 청구할 수 있을 것으로 예상됩니다.
계산 방식은 다음과 같습니다:
- L1 fee를 추정하고 L2 gas로 환산한 뒤,
preVerificationGas로 설정합니다. a. user operation 1개 크기의 bundle을 가정하고, 일반적으로 특수 contract call 형태로 노출되는 네트워크 제공 메서드를 사용해 gas를 추정합니다. b. 이 fee를 L2 gas 값으로 환산하려면 L1 base fee와 L2 base fee를 모두 가정해야 합니다. - L2 unmetered gas를 계산하여 위에서 계산한 값에 더합니다.
a. 이는 일반적인
preVerificationGas계산을 위한 PreVerificationGas 계산 섹션에서 설명한 것과 동일한 방법입니다. eth\_sendUserOperation동안에도 (1)과 (2)를 실행하고, "pre-check" 단계에서preVerificationGas가 충분히 높지 않은 operation은 거부합니다.- bundling 동안에는 제출 직전에 (1)과 (2)를 다시 실행합니다.
a.
preVerificationGas가 충분히 높지 않은 operation은 거부합니다.
이 메커니즘이 동작하기는 하지만, 매우 심각한 UX 문제가 있습니다.
(2) 과정에서 bundler는 gas 계산을 수행하기 위해 L1과 L2 base fee 값을 가정해야 합니다. base fee는 동적이므로, gas 추정 단계와 제출/bundling 단계 사이에 L1\_fee / L2\_fee의 비율이 증가하면 더 높은 preVerificationGas이 필요해지고, 더 낮은 비율로 계산된 user operation은 거부됩니다.
사용자가 이를 개선하기 위해 할 수 있는 최선의 방법은, 추정과 bundling 사이에 비율이 증가할 것이라고 가정하고 preVerificationGas에 여유분(overhead)을 두어 성공 가능성을 높이는 것입니다.
preVerificationGas는 항상 전액 청구되므로 (즉 limit 필드가 아니므로), 사용자는 가격 변동과 무관하게 이 여유분을 부담할 수밖에 없습니다. 사용자는 과다 지불할 가능성과 operation이 거부될 가능성 사이에서 선택할 수밖에 없는 상황에 놓입니다.
💡 Rundler는 위에서 설명한 preVerificationGas 계산을 구현합니다. 이러한 L2의 사용자는 operation이 거부되지 않을 가능성을 높이기 위해 eth\_estimateUserOperationGas가 반환하는 preVerificationGas에 25%의 buffer를 추가하는 것을 권장합니다.
Optimism 엣지 케이스
Optimism의 base fee는 매우 낮아서, 흔히 100 wei(네, wei입니다) 이하입니다. L1 gas fee를 청구하는 데 필요한 preVerificationGas은 L2 gas fee와 반비례 관계이므로, preVerificationGas가 매우 높아야 합니다(수백만 단위).
Optimism의 priority fee는 흔히 base fee보다 몇 자릿수나 높습니다. 따라서 사용자는 네트워크의 priority fee에 비례하는 priority fee를 제출하지 않도록 매우 주의해야 하는데, entry point가 preVerificationGas \(very high\) \* priority fee \(normal\) 에 대한 지불을 요구하기 때문에 엄청난 과다 지불로 이어질 수 있습니다. 이런 이유로 Rundler는 Optimism에서 bundling을 유도하기 위해 priority fee를 base fee의 고정 비율로 설정하도록 요구합니다.
signature aggregator 문제
Signature aggregation은 다음과 같은 이유로 ERC-4337에서 많이 논의되는 기능입니다:
- signature compression을 통해 L2의 calldata 비용을 줄여 상당한 절감 효과를 냅니다.
- aggregated validation check의 gas 비용을 bundle 내 여러 operation에 분산시킵니다. a. 이 validation check은 단순한 BLS signature일 수도 있고, 복잡한 aggregated ZK proof일 수도 있습니다.
현재 버전의 entry point에서는 signature aggregator의 validate function 호출이 계측되지 않습니다. 이는 위의 L2 문제와 마찬가지로, bundler가 aggregated user operation에 이 gas를 청구할 방법을 찾아야 함을 의미합니다.
L2 문제와 마찬가지로, 유일하게 합리적인 방법은 preVerificationGas을 늘리는 것입니다.
한 가지 방법은 다음과 같습니다:
- bundler는
targetbundle 크기를 가정합니다 - bundler는 추정 전에 수신하는 모든 operation에 대해
validateUserOp을 호출하여, 사용된 경우 aggregator 주소를 추출합니다. - aggregated user operation이 수신되면, bundler는 해당 target bundle 크기에서 operation당 signature aggregator가 사용하는 gas 양을 추정해야 합니다.
a. 한 가지 방법은 수신된 user operation을
target번 복제하여 bundle에 넣은 다음aggregator.validateSignatures에eth\_estimateGas을 사용하는 것입니다 b. 다른 방법은 gas 측정치(정적 값과 operation당 동적 값)를 미리 채워둔 signature aggregator whitelist를 유지하는 것입니다. - 추정된 gas를 위의
preVerificationGas계산에 더하고 이 값을 반환합니다.
이 접근 방식에는 몇 가지 문제가 있습니다:
- bundler가
targetbundle 크기를 가정함으로써 위험을 감수합니다. 다음 중 하나입니다: a. bundler가 실제로 target operation을 bundle할 수 있을 때까지 기다림 — latency로 인해 UX가 저하됨 b. bundler가 target보다 적게 bundle하고 비용을 부담함 - 사용자는 얼마나 빨리 포함되고 싶은지에 따라 더 많거나 더 적게 "입찰"할 수 없습니다.
a. limit 기반 접근 방식에서는, 사용자가 빠른 채굴을 보장받고 싶다면 비용을 과대 추정할 수 있습니다. 실제 비용이 더 낮게 나오면 과다 청구되지 않습니다. 이 접근 방식에서는
preVerificationGas가 고정값이므로, 사용자는 항상 입찰한 전액을 지불해야 합니다. - P2P 네트워크에서는 bundler마다 target bundle 크기가 다를 수 있습니다.
a. 이는 추정에 사용된 bundler가 mempool 내 다른 bundler가 요구하는
preVerificationGas를 과대 또는 과소 추정할 수 있음을 의미합니다. b. 이러한 오프체인 가정은 mempool의 상호 운용성을 저해합니다.
이러한 복잡성 때문에 Rundler는 현재 signature aggregator를 지원하지 않습니다. 위에서 설명한 방법을 추가하고 어느 정도(작은 값, 1부터 시작) bundle 크기를 가정할 가능성이 있는데, 이는 signature aggregator 사용을 매우 비싸게 만들 것입니다.
entry point의 잠재적 변경 사항
위의 문제들은 모두 user operation에 의한 상당한 gas 사용량을 entry point contract가 계측하지 않기 때문에 발생합니다. 이 gas 사용량을 청구하기 위해 preVerificationGas에 의존하는 것은, 사용자의 UO가 온체인에 빠르게 포함될 가능성을 높이기 위해 실제 사용량보다 더 많이 지불해야 한다는 심각한 UX 문제를 안고 있습니다.
이러한 문제에 대한 해결책으로는 entry point contract를 수정해 이 추가 gas 사용량을 계측하고, 이를 limit 기반 gas 필드에 귀속시키는 방법이 있을 수 있습니다.
L2-L1 calldata gas 계측
💡 이는 어려운 문제에 대한 매우 대략적인 해결책 개요입니다. 커뮤니티의 아이디어를 듣고 싶습니다!
L1 calldata gas 비용은 온체인에서 계측할 수 있으며, user operation은 overhead가 아니라 실제로 발생한 정확한 비용만큼만 청구될 수 있습니다. limit 기반 필드를 사용해야 합니다.
가능한 해결책은 새로운 필드인 daCallDataGasLimit(da는 Data Availability의 약자로, 임시 명칭)을 도입하는 것입니다. 이 필드는 entry point의 L2+ 버전에 네이티브로 존재하며, 트랜잭션 calldata가 다른 시스템에 게시되어 별도의 방식으로 청구되어야 하는 체인에서 사용됩니다.
entry point 로직은 다음과 같습니다:
- 배포 시 entry point는
measureUserOperationDaGas\(UserOperation userOp\)라는 단일 함수를 가진 helper contractdaGasMeter과 연결됩니다 a. 이 함수는 user operation을 받아 정확히 얼마나 많은 DA gas가 사용되었는지 측정합니다. b. 예를 들어 Arbitrum에서는 in-memory user operation으로gasEstimateL1Component을 호출하여 얼마나 많은 L1 gas를 사용했는지 거의 정확하게 알아낼 수 있습니다(여러 operation이 있는 bundle로 인한 추가 압축은 반영할 수 없습니다). - entry point는 validation 전에 각 user operation에 대해 이 함수를 호출하고, 이 gas를
daCalldataGasLimit에 귀속시킬 수 있습니다. - revert를 피하기 위해, 사용된 DA gas가
daCalldataGasLimit보다 클 경우 revert하는 대신 entry point는 그 지점에서 값을 제한하고, bundler는 이 limit을 초과하는 gas를 부담하게 됩니다. bundler는 bundling 전에 bundle된 operation이 limit 필드에 충분히 높은 buffer를 갖도록 함으로써 오프체인에서 이를 관리할 수 있습니다.
이 접근 방식에는 몇 가지 꽤 심각한 단점이 있습니다:
- 서로 다른 체인의 entry point contract는 각기 다른 주소를 갖게 됩니다.
- 측정 중 gas 사용량이 발생합니다. a. L2+에서는 일반적으로 execution gas 비용이 data gas 비용보다 훨씬 낮으므로 이는 덜 심각한 문제입니다.
signature aggregator gas 계측
entry point contract는 aggregator.validateSignatures 호출 중 사용된 gas 양을 측정하고, 이를 aggregate된 user operation 수로 나눈 뒤, verificationGasLimit에서 차감하여 gas 사용량을 균등하게 귀속시키도록 수정할 수 있습니다.
whitelist에 등록된 각 signature aggregator는 aggregated signature를 검증하기 위한 기본 비용을 나타내는 정적 값과, aggregated operation당 비용 증가를 나타내는 동적 값을 가져야 합니다. 예를 들어 BLS signature aggregator는 정적 값으로 일회성 signature verification 비용을, 동적 값으로 operation당 hashing operation 비용을 가질 수 있습니다. bundler는 eth\_estimateUserOperationGas 동안 정적 값을 target bundle 크기로 나눈 값에 동적 값을 더해 verificationGasLimit를 늘릴 수 있습니다.
target bundle 크기는 어떻게 설정할까?
여기서 가능한 해결책은 eth\_estimateUserOperationGas의 인자에 minimumBundleSize을 추가하는 것으로, 이는 사용자가 포함되기를 원하는 가장 작은 bundle 크기(즉 가장 높은 gas)에 해당합니다. 더 많이 지불할 의향이 있는 사용자는 최소 bundle 크기를 줄여 포함 시간을 개선할 수 있습니다.
그러면 bundler는 자신이 포함하는 UO가 해당 UO의 최소 bundle 크기보다 크거나 같은 bundle에만 포함되도록 하는 로직이 필요합니다. 이 최소 bundle 크기는 simulation 과정에서 account validation 단계에서 사용된 gas 양을 추적하고, 이를 verificationGasLimit 에서 뺀 다음, 남은 값으로부터 최소 크기를 계산하는 방식으로 계산할 수 있습니다. bundler는 이 값을 mempool 내 UO와 함께 저장하고 bundle 구성 시 힌트로 사용할 수 있습니다.
💡 이 접근 방식의 한 가지 단점은 signature aggregator의 gas 사용량이 operation마다 균일하다고 가정한다는 점입니다. 그렇지 않은 경우, 계측을 aggregator contract로 넘겨 verification function에서 반환하도록 할 수 있습니다. 이 경우 bundler는 이런 비균일 값을 오프체인에서 계산할 방법도 필요합니다.
이것이 signature aggregator 개발자에게 의미하는 바는?
signature aggregator는 bundler에게 오프체인 signature 계산 메서드와 정적/동적 gas 비용 구성 요소를 제공하여 bundler로부터 직접 whitelist에 등록되어야 할 가능성이 높습니다. 콜드 스타트 문제는 특히 사용자가 operation 속도를 높이기 위해 "입찰"할 수 없다는 점을 고려하면 까다로울 것입니다.
이것이 account client 개발자에게 의미하는 바는?
특히 gas fee를 추정할 때가 되면 위에서 설명한 L2 간의 차이를 이해하는 것이 중요합니다. Optimism에서는 네트워크가 제공하는 priority fee를 사용할 경우, 이 priority fee가 L1 비용에도 적용되기 때문에 user operation에 대해 엄청나게 과다 지불할 수 있습니다. Alchemy의 bundler endpoint를 사용하는 경우, fee 추정에 대한 팁은 저희 문서를 참고하세요.
🦀
계속 읽기
이 ERC-4337 gas 추정 심층 분석의 다음 글에서는 user operation fee 추정 과정을 살펴봅니다. 1부나 2부를 놓치셨다면, ERC-4337 gas 추정, dummy 값, token transfer 문제가 어떻게 동작하는지 확인해 보세요.
Alchemy 뉴스레터
출시 소식을 가장 먼저 받아보세요
뉴스레터 구독하기
Alchemy의 최신 제품 업데이트와 리소스 받기
이메일 주소를 입력하면 마케팅 커뮤니케이션 및 제품 업데이트 수신에 동의하게 됩니다. Alchemy는 저희 개인정보 처리방침에 따라 수집한 정보를 처리합니다. 언제든지 구독을 취소할 수 있습니다.
관련 아티클

Glamsterdam: Ethereum 개발자를 위한 완전 가이드
Glamsterdam이 Sepolia에서 가동 중입니다. 개발자에게 무엇을 의미하는지, 그리고 Alchemy가 네트워크 업그레이드에 어떻게 준비했는지를 담은 완전 가이드입니다.

트레이딩 팀이 저지연 RPC로 Alchemy를 선택하는 이유
트레이딩 팀이 Alchemy를 선택하는 이유는, 시장이 움직일 때의 저지연 읽기와 쓰기, 그리고 거래량이 정점에 달해도 자금이 정산될 때의 신뢰할 수 있는 기록 때문이다.

도쿄에서 구축한다면 어떤 RPC 제공업체를 선택해야 할까
도쿄를 서비스하는 RPC 제공업체 다섯 곳을 다섯 개 체인에서 벤치마크했습니다. 비교 결과와, 지연 시간에 민감한 팀에게 차이가 어디서 나는지 정리합니다.