sherlock-2025-06-symbiotic-relay-m06

[M-06] BlsBn254 is not available in certain chains due to hardcoded gas limit

보고서

Summary

체인별로 precompile의 가스 비용은 서로 다르게 설정될 수 있다. precompile을 호출할 때 하드코딩된 gas limit을 사용하므로 특정 체인에서 EcParing precompile이 항상 실패한다. 따라서 일부 체인에서 BlsBn254를 사용할 수 없다.

Keyword

precompile, gas limit, zksync, erc1108, cross chain

Vulnerability

SigBlsBn254.verify 에서는 BN254.safePairing를 호출할 때 하드코딩된 PAIRING_CHECK_GAS_LIMIT(120_000)를 이용한다. 이는 Ethereum의 EIP-1108에서 결정된 34000 * k + 45000 를 기준으로, k=2일때 필요한 EcParing 가스 비용을 계산한 것이다.

@>  uint256 internal constant PAIRING_CHECK_GAS_LIMIT = 120_000;
 
    function verify(
        bytes memory keyBytes,
        bytes memory message,
        bytes memory signature,
        bytes memory extraData
    ) internal view returns (bool) {
        ...
 
        (bool success, bool result) = BN254.safePairing(
            signatureG1.plus(keyG1.scalar_mul(alpha)),
            BN254.negGeneratorG2(),
            messageG1.plus(BN254.generatorG1().scalar_mul(alpha)),
            keyG2,
@>          PAIRING_CHECK_GAS_LIMIT
        );
        return success && result;
    }
 
    ////////////////////////////
    // BN254.safePairing
    function safePairing(
        G1Point memory a1,
        G2Point memory a2,
        G1Point memory b1,
        G2Point memory b2,
@>      uint256 pairingGas
    ) internal view returns (bool, bool) {
        ...
 
        assembly {
@>          success := staticcall(pairingGas, 8, input, mul(12, 0x20), out, 0x20)
        }
        ...
    }

precompile 의 가스 비용은 변경되거나 체인별로 다를 수 있다. 예를 들어 ZKSync(배포되는 체인에 포함됨)는 May, 2025에 ZIP-11. V28 Precompile Upgrade 업그레이드에서 EcAdd, EcMul, EcPairing precompile을 업데이트하고 가스 비용을 변경하였다.

위 하드코드는 ZKSync에서 문제를 일으킨다. 다음은 ZKSync V28에서 업데이트된 EcPairing 코드이다. 가스 비용은 80000 * k 로 계산된다. k=2일 때 필요한 가스 비용은 160_000 으로 PAIRING_CHECK_GAS_LIMIT 보다 높다. 가스가 부족하면 EcParing 은 항상 실패하므로 ZKSync에서 BlsBn254 서명 확인은 항상 실패하게 된다.

function ECPAIRING_BASE_GAS_COST() -> ret {
    ret := 0
}
 
function ECPAIRING_PAIR_GAS_COST() -> ret {
@>  ret := 80000
}
 
function ecpairingGasCost(pairs) -> ret{
@>  let gasPerPairs := mul(ECPAIRING_PAIR_GAS_COST(), pairs)
    ret := add(ECPAIRING_BASE_GAS_COST(), gasPerPairs)
}

Impact

일부 체인에서 BlsBn254 를 이용할 수 없음

Mitigation

Precompile을 호출하는 데 필요한 가스 비용은 미래에 얼마든지 변경될 수 있으며 체인마다 다를 수 있다. 따라서 PAIRING_CHECK_GAS_LIMIT 로 하드코딩하는 대신 관리자가 설정 가능한 변수를 이용해야 한다.

Memo

(오딧 당시) ZIP-11. V28 Precompile Upgrade 는 ZKSync 메인넷에만 확인할 수 있다(테스트넷에는 적용되지 않은 것 같다). 또한 foundry fork 테스트로도 재현할 수 없었다. (foundry-zksync를 이용해야 함)


tags: bughunting, symbiotic, smart contract, solidity, cross chain, restaking, severity medium, precompile, gas limit, gas, zksync, erc1108