[Code4rena] Stakehouse - 2편

0xDave·2022년 11월 18일
0

Ethereum

목록 보기
59/112

중간 점검 🤯


그 동안 짧막한 코드만 보다가 하나의 프로젝트 코드를 전부 보려고 하니 어려움이 있었다. LOC가 그렇게 많지 않음에도 코드를 읽는 것만 해도 거의 이틀 정도 걸린 것 같다. 심지어 가장 코드가 많은 LiquidStakingManager.sol은 아직 다 읽지도 않았다. 게다가 모든 코드를 확실히 이해했다고 볼 수도 없고 누가 어떤 부분을 물어보면 70퍼 수준에서 내가 이해한 만큼 설명할 정도다. 반복해서 코드를 보면서 읽는 속도는 조금 나아진 것 같다. 하지만 객관적으로 보면 아직 한참 멀었다.


Tool 사용하기 🛠


이번에 처음 사용해본 툴을 몇 가지 소개하고자 한다. 100% 활용했다고는 못 해도 많은 도움을 얻었다고 할 수 있다.

1. Surya

길고 긴 코드를 비주얼로 한 눈에 보여주는 툴이다. 각 컨트랙트 안에 있는 변수와 함수의 구조를 파악할 수 있고, 전체 컨트랙트간의 관계를 살펴볼 수 있다. ConsenSys에서 제공하는 툴로 사용 방법은 깃헙 페이지에서 확인 가능하다.


2. Inline Bookmarks

이것도 ConsenSys에서 제공하는 extension이다. vsc에서 검색해서 다운 받을 수 있다. 취약점을 발견하거나 코드에 메모한 것들을 나중에 다시 찾아볼 때 유용하다.


claimRewards 💰


내가 생각하는 취약점을 몇 가지 기록해보고자 한다. 내가 틀릴수도 있지만 나중에 리포트가 나오면 복기를 하기 위함이다.

//GiantMevAndFeesPool.sol

    function claimRewards(
        address _recipient,
        address[] calldata _stakingFundsVaults,
        bytes[][] calldata _blsPublicKeysForKnots
    ) external {
        uint256 numOfVaults = _stakingFundsVaults.length;
        require(numOfVaults > 0, "Empty array");
        require(numOfVaults == _blsPublicKeysForKnots.length, "Inconsistent array lengths");
        for (uint256 i; i < numOfVaults; ++i) {
            StakingFundsVault(payable(_stakingFundsVaults[i])).claimRewards(
                address(this),
                _blsPublicKeysForKnots[i]
            );
        }

        updateAccumulatedETHPerLP();

        _distributeETHRewardsToUserForToken(
            msg.sender,
            address(lpTokenETH),
            lpTokenETH.balanceOf(msg.sender),
            _recipient
        );
    }

위 함수는 stakingFundsVaults에 모인 reward를 반복문을 돌려서 claim한다. 그런데 stakingFundsVaults가 매우 많다면 out of gas가 발생하면서 중간에 클레임 되지 않는 vault가 생길 수 있다. 따라서 한 번에 클레임 할 수 있는 vault의 수를 제한하는 것이 안전하다.

몇 가지 더 취약점을 발견할 뻔(?) 했으나 이를 방지하는 코드가 이미 잘 짜여있어서 아쉽게 추가적인 취약점은 발견하지 못했다.


후기 🧑‍💻


코드를 전부 이해하지 못한 나 조차도 생각보다 코드가 촘촘하게 잘 짜여졌다는 느낌을 받았다. Stakehouse는 이번 컨테스트 말고도 이전에 여러 회사에게 Audit을 받았기 때문에 더 그런 것 같다. 이미 Audit을 받았으면 취약점이 더 이상 없는 것 아니냐는 생각이 들 수 있다. 하지만 몇 달 전 OpenSea 콘테스트에서도 매우 큰 취약점이 발견 됐듯이, 이미 오딧을 여러 번 받았다고 해도 코드를 업데이트 하면서 취약점이 생길 수 있다. 이번 콘테스트에 참여하면서 스스로 피드백을 해보자면


  1. 프로젝트 파악은 최대한 짧게
    이번에 처음 콘테스트에 참여하면서 코드를 보기 전에 프로젝트에 대해 리서치 먼저 했었다. 현재도 이렇게 하는 것이 순서가 맞다고 생각한다. 하지만 콘테스트 기한은 한정적이기 때문에(보통 짧게는 3일 길게는 7일 정도) 리서치에 많은 시간을 할애하기 보다 코드 리뷰를 하면서 중간 중간 이해 안 되는 부분은 공식 독스를 보는 것이 낫다.

  2. 과거로 부터 배우기
    Secureum의 Audit Findings 101을 읽었다고 하더라도 취약점을 발견하는 실력은 아직 형편없다. 가장 좋은 방법은 직접 콘테스트에 참여하면서 동시에 과거 리포트를 꾸준히 보는 것이다. Code4rena에서 지금까지 있었던 콘테스트의 리포트를 발행하니 교과서 보듯이 보는 게 맞다고 생각한다.

  3. foundry 배우기
    취약점을 공격할 수 있는 시나리오가 머릿속에 그려진다면 직접 테스트를 해봐야 한다. 테스트 하는 방법은 여러가지가 있겠지만 Stakehouse에서 제공한 테스트 코드 템플릿은 foundry로 되어 있었다. foundry는 현재 리믹스 못지 않게 빌더들에게 가장 사랑받는 개발툴이다. 안 그래도 예전부터 배우려고 했었기 때문에 이 참에 배워두면 많은 도움이 될 것이다.


누구는 현재 Code4rena에 많은 사람들이 몰려서 레드오션이 됐다고 말한다. 나는 2~3년 전의 유튜브 시장이 지금의 Code4rena와 비슷하다고 생각한다. 크립토 쪽과 메인스트림 쪽을 비교하는 것이 적절하지 않을 수 있다. 하지만 개인적인 의견을 말하자면, 예전 유튜브가 레드오션이라는 말이 있을 때 지금 들어가면 먹을 것 없다고 말해도 결국 잘 될 사람은 자신의 색이 담긴 영상을 내놓고 구독자를 모아서 채널을 키워 잘 됐다. Code4rena에 참여하는 사람들이 많아졌다고 해도 현재 리더보드를 보면 아직도 많은 상금을 타가는 사람들이 존재한다.

자신이 실력을 키울 생각과 행동력이 있으면 아직 늦지 않았다고 생각한다. 직접 경험하기 전까지 그 시장을 레드오션이라고 단언할 수는 없다. 내가 Audit을 배우려고 하는 이유는 쌓은 경험들이 실력으로 이어지고 내 것이 된 실력은 매우 큰 가치를 지닐 것이라고 생각하기 때문이다. 지금 당장 제대로 된 결과가 보이지 않는 것은 당연하다. 콘테스트에 계속 참가하고 실력을 쌓아가면 리더보드에 이름이 적히는 날이 분명히 올 것이라 생각한다.

profile
Just BUIDL :)

0개의 댓글