블록체인Mar 28, 2026
Deep EVM #7: Yul의 가스 효율적 루프와 조건문
OS
Open Soft Team
Engineering Team
루프는 가스가 죽는 곳이다
대부분의 스마트 컨트랙트에서 가장 큰 가스 소비자는 반복입니다. 100개 요소 배열을 순회하는 함수는 본문을 100번 실행합니다 — 본문 안의 모든 옵코드가 100배로 곱해집니다.
Yul For 루프의 해부학
for { let i := 0 } lt(i, 10) { i := add(i, 1) } {
// 본문
}
반복당 루프 오버헤드:
- 조건 검사: 23 가스
- 후행 반복: 6 가스
- 점프 복귀: 11 가스
- 반복당 총 오버헤드: 40 가스
벤치마크 결과 (100개 요소)
| 방법 | 반복당 가스 | 총합 (100요소) | Solidity 대비 절감 |
|---|---|---|---|
| Solidity (checked) | ~73 | 7,300 | 기준 |
| Solidity (unchecked) | ~53 | 5,300 | 27% |
| Yul | ~43 | 4,300 | 41% |
루프 언롤링
루프 언롤링은 반복당 여러 요소를 처리하여 요소당 오버헤드를 줄입니다:
function sumUnrolled(offset, length) -> total {
let end := add(offset, mul(length, 0x20))
let endAligned := sub(end, mod(mul(length, 0x20), 0x80))
for { } lt(offset, endAligned) { offset := add(offset, 0x80) } {
total := add(total, calldataload(offset))
total := add(total, calldataload(add(offset, 0x20)))
total := add(total, calldataload(add(offset, 0x40)))
total := add(total, calldataload(add(offset, 0x60)))
}
for { } lt(offset, end) { offset := add(offset, 0x20) } {
total := add(total, calldataload(offset))
}
}
Yul에서 안전한 unchecked 산술
Yul의 모든 산술은 기본적으로 unchecked입니다. 오버플로우 검사가 필요할 때:
function safeAdd(a, b) -> c {
c := add(a, b)
if lt(c, a) { revert(0, 0) }
}
결론
Yul의 루프 최적화는 영리한 트릭이 아닙니다 — 루프 본문의 모든 옵코드의 정확한 가스 비용을 이해하고 체계적으로 낭비를 제거하는 것입니다. 스토리지 읽기 캐시, 타이트 루프 언롤, 조기 종료, 반복 대신 비트 연산 선호.