devops

Arbitrum Layer 2 GasPricing 모델 본문

Layer2

Arbitrum Layer 2 GasPricing 모델

vataops 2023. 4. 2. 17:38
반응형

아비트럼은 이더리움의 ETH가 가스비로 사용된다. 현재 $ARB 라는 거버넌스 토큰이 발행되었지만, $ARB 는 유틸리티는 단지 '거버넌스'에 한정되어있고 Arbitrum실제 트랜잭션 수수료엔 ETH가 사용된다.

시퀀서는 Arbos를 통해서 L2 가스비를 계산하여 유저로부터 가스비를 징수하고 전달받은 트랜잭션을 Batch화 하여 L1 Sequencer Inbox Contract의 Calldata로 전송한다.

L2Fees.info

여기서 Arbitrum 체인 운영에서 가장 많은 비중을 차지하는 비용이 이 calldata에 Tx Batch를 전송하는 ETH 가스비다. L2의 Tx를 Batch화할 때 압축과 인코딩 과정을 거치는데, 얼마나 효율적으로 크기를 줄이느냐에 따라 L1 트랜잭션 비용이 결정된다. 이 비용이 저렴할 수 록 아비트럼 L2 Tx 가스비 또한 낮아지기 때문에 아주 중요하다.

여기서 압축은 구글에서 개발한  'brotli'라는 알고리즘이 사용된다.

https://github.com/google/brotli

 

GitHub - google/brotli: Brotli compression format

Brotli compression format. Contribute to google/brotli development by creating an account on GitHub.

github.com

# nitro/arbcompress/comporess_wasm.go

func compressLevel(input []byte, level int) ([]byte, error) {
	maxOutSize := compressedBufferSizeFor(len(input))
	outBuf := make([]byte, maxOutSize)
	outLen := brotliCompress(input, outBuf, level, WINDOW_SIZE)
	if outLen < 0 {
		return nil, fmt.Errorf("failed compression")
	}
	return outBuf[:outLen], nil
}

 

1 Batch 당 약 900~1000개의 Tx가 롤업된다.

Arbitrum($0.06)이 대표적인 옵티미스틱 롤업 중 하나인 Optimism($0.12)보다 가스비가 저렴한 이유는 Batch 처리가 더욱 효율적이기 때문이라고 생각한다. (아비트럼은 하한선도 정해져있다. Arbitrum One은 0.1 gwei, Nova는 0.01 gwei)

Arbitrum Inbox에 Batch를 전송하는 위 Tx의 Tx Fee는 약 $55

유저들의 직접적인 비용인 L2 Pricing은 아비트럼의 Arbos가 처리한다.

L2 가스비는 User demand, geth의 상태, 연산 속도 리밋과 같은 다양한 요소들을 통해서 책정된다. L2PricingState의 대부분은 ArbGasInfo, ArbOwner의 precompile을 통해서 액세스하며 대부분의 상태변화는 자동으로 이루어진다. 이는 블록생성과 트랜잭션 Hook 중에 발생한다. 

Arbos의 GasPool은 per-Block limit을 결정하고, L2 Block이 가질 수 있는 가스 양에 대한 Dynamic Upper limit을 설정한다. 이는 GasChargingHook()에서 수행되는데 GasChargingHook는 Poster가 L1 Calldata비용을 충당할 수 있도록 유저로부터 가스비를 확보하게 한다. 

# nitro/arbos/l2pricing/l2pricing.go

type L2PricingState struct {
	storage             *storage.Storage
	speedLimitPerSecond storage.StorageBackedUint64
	perBlockGasLimit    storage.StorageBackedUint64
	baseFeeWei          storage.StorageBackedBigUint
	minBaseFeeWei       storage.StorageBackedBigUint
	gasBacklog          storage.StorageBackedUint64
	pricingInertia      storage.StorageBackedUint64
	backlogTolerance    storage.StorageBackedUint64
}

위는 L2PricingState의 파라미터들이다. 이 값들은 위에서 언급한 것과 같이 동적으로 변화하게된다. 초기 설정은 다음과 같다.

# nitro/arbos/l2pricing/model.go

const InitialSpeedLimitPerSecondV0 = 1000000
const InitialPerBlockGasLimitV0 uint64 = 20 * 1000000
const InitialSpeedLimitPerSecondV6 = 7000000
const InitialPerBlockGasLimitV6 uint64 = 32 * 1000000
const InitialMinimumBaseFeeWei = params.GWei / 10
const InitialBaseFeeWei = InitialMinimumBaseFeeWei
const InitialGasPoolSeconds = 10 * 60
const InitialRateEstimateInertia = 60
const InitialPricingInertia = 102
const InitialBacklogTolerance = 10

각 파라미터에 대한 간단한 설명을 붙이자면,

  • const InitialSpeedLimitPerSecondV0 = 1000000 // 초기 블록 생성 속도 제한 
  • const InitialPerBlockGasLimitV0 uint64 = 20 * 1000000 // 블록이 생성될 때 마다 사용가능한 가스양 제한 
  • const InitialSpeedLimitPerSecondV6 = 7000000  // 초기 블록 생성 속도 제한 (버전 차이로 추정)
  • const InitialPerBlockGasLimitV6 uint64 = 32 * 1000000  // // 블록이 생성될 때 마다 사용가능한 가스양 제한 
  • const InitialMinimumBaseFeeWei = params.GWei / 10 // 초기 최소 BaseFeeWei 설정 
  • const InitialBaseFeeWei = InitialMinimumBaseFeeWei 
  • const InitialGasPoolSeconds = 10 * 60  // 초기 가스 풀 유효 시간
  • const InitialRateEstimateInertia = 60 // 가격 추정 Inertia
  • const InitialPricingInertia = 102 // 가격 모델링 Inertia
  • const InitialBacklogTolerance = 10 // 초기 대기열 허용 한도
func (ps *L2PricingState) UpdatePricingModel(l2BaseFee *big.Int, timePassed uint64, debug bool) {
	speedLimit, _ := ps.SpeedLimitPerSecond()
	_ = ps.AddToGasPool(int64(timePassed * speedLimit))
	inertia, _ := ps.PricingInertia()
	tolerance, _ := ps.BacklogTolerance()
	backlog, _ := ps.GasBacklog()
	minBaseFee, _ := ps.MinBaseFeeWei()
	baseFee := minBaseFee
	if backlog > tolerance*speedLimit {
		excess := int64(backlog - tolerance*speedLimit)
		exponentBips := arbmath.NaturalToBips(excess) / arbmath.Bips(inertia*speedLimit)
		baseFee = arbmath.BigMulByBips(minBaseFee, arbmath.ApproxExpBasisPoints(exponentBips))
	}
	_ = ps.SetBaseFeeWei(baseFee)
}

 

이 파라미터들은 마지막 블록과 함께 UpdatePricingModel()이 호출되어 파라미터가 수정된다.

Arbitrum Node를 통해서 L2 가격에 대해서 실시간으로 확인하고 싶다면 RPC로 eth_estimateGas를 호출해보면 된다.

반응형
Comments