code-423n4 / 2024-01-salty-findings

6 stars 3 forks source link

Airdroped user can bypass the walletHasAccess restriction #426

Open c4-bot-8 opened 6 months ago

c4-bot-8 commented 6 months ago

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/staking/Staking.sol#L43

Vulnerability details

The walletHasAccess restriction is a significant legal safeguard that limits users residing in certain marked countries from participating as liquidity providers or staking the SALT token. This precaution is in place due to the existence of cryptocurrency restrictions in some countries.

Bypassing this check can potentially lead to legal complications for the project. That's the case for airdrop users that it get a directly increase of share in the staking contract due that this tokens are been depositing direclty in the staking contract:

function transferStakedSaltFromAirdropToUser(address wallet, uint256 amountToTransfer) external
        {
        require( msg.sender == address(exchangeConfig.airdrop()), "Staking.transferStakedSaltFromAirdropToUser is only callable from the Airdrop contract" );

        _decreaseUserShare( msg.sender, PoolUtils.STAKED_SALT, amountToTransfer, false );
        _increaseUserShare( wallet, PoolUtils.STAKED_SALT, amountToTransfer, false );  <---------

        emit XSALTTransferredFromAirdrop(wallet, amountToTransfer);
        }

[Link]

Impact

Airdrop users can bypass the walletHasAccess restriction, leading to legal problems for the protocol.

Proof of Concept

The wallet is passing directly to the staking without check for the walletHasAcces restriction:

function transferStakedSaltFromAirdropToUser(address wallet, uint256 amountToTransfer) external
        {
        require( msg.sender == address(exchangeConfig.airdrop()), "Staking.transferStakedSaltFromAirdropToUser is only callable from the Airdrop contract" );

        _decreaseUserShare( msg.sender, PoolUtils.STAKED_SALT, amountToTransfer, false );
        _increaseUserShare( wallet, PoolUtils.STAKED_SALT, amountToTransfer, false );  <---------

        emit XSALTTransferredFromAirdrop(wallet, amountToTransfer);
        }

[Link]

function stakeSALT( uint256 amountToStake ) external nonReentrant { require( exchangeConfig.walletHasAccess(msg.sender), "Sender does not have exchange access" ); <-------

    // Increase the user's staking share so that they will receive more future SALT rewards.
    // No cooldown as it takes default 52 weeks to unstake the xSALT to receive the full amount of staked SALT back.
    _increaseUserShare( msg.sender, PoolUtils.STAKED_SALT, amountToStake, false );

    // Transfer the SALT from the user's wallet
    salt.safeTransferFrom( msg.sender, address(this), amountToStake );

    emit SALTStaked(msg.sender, amountToStake);
    }

[Link]

Tools Used

Manual

Recommended Mitigation Steps

Ensure that airdropped users have the necessary access, otherwise explore alternative strategies for claiming airdrops, such as utilizing a merkle tree.

Assessed type

Other

c4-judge commented 5 months ago

Picodes marked the issue as duplicate of #964

c4-judge commented 5 months ago

Picodes changed the severity to QA (Quality Assurance)