Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Griefing Attack Possible Where Validator Will Lose Their Stake #369

Open
c4-bot-8 opened this issue May 27, 2024 · 0 comments
Open

Griefing Attack Possible Where Validator Will Lose Their Stake #369

c4-bot-8 opened this issue May 27, 2024 · 0 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working 🤖_03_group AI based duplicate group recommendation

Comments

@c4-bot-8
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2024-05-arbitrum-foundation/blob/main/src/assertionStakingPool/AssertionStakingPool.sol#L40
https://github.com/code-423n4/2024-05-arbitrum-foundation/blob/main/src/assertionStakingPool/EdgeStakingPool.sol#L44

Vulnerability details

Proof of Concept

Flow

  1. Create a Pool: Any validator can use the createPool function to create a new AssertionStakingPool.
File: AssertionStakingPoolCreator.sol

    function createPool(
        address _rollup,
        bytes32 _assertionHash
    ) external returns (IAssertionStakingPool) {
        AssertionStakingPool assertionPool = new AssertionStakingPool{salt: 0}(_rollup, _assertionHash);
        emit NewAssertionPoolCreated(_rollup, _assertionHash, address(assertionPool));
        return assertionPool;
    }
  1. Deposit Tokens: Validators deposit tokens into the staking pool using the depositIntoPool function.
File: AbsBoldStakingPool.sol

    function depositIntoPool(uint256 amount) external {
        if (amount == 0) {
            revert ZeroAmount();
        }

        depositBalance[msg.sender] += amount;
        IERC20(stakeToken).safeTransferFrom(msg.sender, address(this), amount);

        emit StakeDeposited(msg.sender, amount);
    }
  1. Create Assertions: Using the deposited tokens, validators can create new assertions with the createAssertion function.
File: AssertionStakingPool.sol

    function createAssertion(AssertionInputs calldata assertionInputs) external {
        uint256 requiredStake = assertionInputs.beforeStateData.configData.requiredStake;
        // approve spending from rollup for newStakeOnNewAssertion call
        IERC20(stakeToken).safeIncreaseAllowance(rollup, requiredStake);
        // reverts if pool doesn't have enough stake and if assertion has already been asserted
        IRollupUser(rollup).newStakeOnNewAssertion(requiredStake, assertionInputs, assertionHash, address(this));
    }

Important things to note about this function

  • No access control in createAssertion.

  • The required stake tokens are directly approved and transferred without verifying the caller's authorization.

Griefing Attack Scenario

  1. Alice creates a new AssertionStakingPool and deposits X tokens.

  2. Attacker frontruns Alice by calling createAssertion with incorrect assertionInputs.

  3. Alice unknowingly becomes a malicious validator due to the incorrect assertion and loses her stake.

Similar situation will happen with EdgeStakingPool contract as well while creating new edge through createEdge function.

  1. Alice creates a new EdgeStakingPool and deposits X tokens.

  2. Attacker frontruns Alice by calling createEdge with incorrect CreateEdgeArgs.

  3. Alice unknowingly becomes a malicious due to the incorrect edge and loses her stake.

Impact

Validators can lose their stake due to incorrect assertions being made on their behalf.

Tools Used

VS Code

Recommended Mitigation Steps

Implement access control to ensure that only the validator who deposited the tokens can create assertions or edges.

File: AssertionStakingPool.sol

    function createAssertion(AssertionInputs calldata assertionInputs) external {
        uint256 requiredStake = assertionInputs.beforeStateData.configData.requiredStake;
+       require(depositBalance[msg.sender] >= requiredStake);
        // approve spending from rollup for newStakeOnNewAssertion call
        IERC20(stakeToken).safeIncreaseAllowance(rollup, requiredStake);
        // reverts if pool doesn't have enough stake and if assertion has already been asserted
        IRollupUser(rollup).newStakeOnNewAssertion(requiredStake, assertionInputs, assertionHash, address(this));
    }
File: EdgeStakingPool.sol

    function createEdge(CreateEdgeArgs calldata args) external {
        uint256 requiredStake = EdgeChallengeManager(challengeManager).stakeAmounts(args.level);
+       require(depositBalance[msg.sender] >= requiredStake);
        IERC20(stakeToken).safeIncreaseAllowance(address(challengeManager), requiredStake);
        bytes32 newEdgeId = EdgeChallengeManager(challengeManager).createLayerZeroEdge(args);
        if (newEdgeId != edgeId) {
            revert IncorrectEdgeId(newEdgeId, edgeId);
        }
    }

Assessed type

Invalid Validation

@c4-bot-8 c4-bot-8 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels May 27, 2024
c4-bot-7 added a commit that referenced this issue May 27, 2024
@c4-bot-12 c4-bot-12 added the 🤖_03_group AI based duplicate group recommendation label May 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working 🤖_03_group AI based duplicate group recommendation
Projects
None yet
Development

No branches or pull requests

2 participants