code-423n4 / 2023-07-reserve-findings

0 stars 0 forks source link

Rewards might be locked inside the contract by setting the wrong token. #29

Open code423n4 opened 11 months ago

code423n4 commented 11 months ago

Lines of code

https://github.com/reserve-protocol/protocol/blob/9ee60f142f9f5c1fe8bc50eef915cf33124a534f/contracts/plugins/assets/stargate/StargateRewardableWrapper.sol#L21

Vulnerability details

Impact

Stakers won't get any rewards and the rewards might be locked inside the contract.

Proof of Concept

In StargateRewardableWrapper, it sets pool, stakingContract, and stargate(reward token).

    constructor(
        string memory name_,
        string memory symbol_,
        IERC20 stargate_,
        IStargateLPStaking stakingContract_,
        IStargatePool pool_
    ) RewardableERC20Wrapper(pool_, name_, symbol_, stargate_) { //@audit should validate stargate 
        require(
            address(stargate_) != address(0) &&
                address(stakingContract_) != address(0) &&
                address(pool_) != address(0),
            "Invalid address"
        );

        uint256 poolLength = stakingContract_.poolLength();
        uint256 pid = type(uint256).max;
        for (uint256 i = 0; i < poolLength; ++i) {
            if (address(stakingContract_.poolInfo(i).lpToken) == address(pool_)) {
                pid = i;
                break;
            }
        }
        require(pid != type(uint256).max, "Invalid pool");

        pool_.approve(address(stakingContract_), type(uint256).max); // TODO: Change this!

        pool = pool_;
        poolId = pid;
        stakingContract = stakingContract_;
        stargate = stargate_;
    }

It checks if pool exists in the stakingContract during the construction but doesn't validate stargate at all.

So users won't receive any rewards like the below.

  1. The stakingContract contains pool and stargate as a reward token.
  2. During the construction, pool and stargateWrong were set.
  3. When users deposit/withdraw the underlying funds, the rewards will be accumulated with stargateWrong token in _claimAndSyncRewards. And the reward amount will be 0 always.
  4. But in _claimAssetRewards(), the real rewards of stargate are transferred to the contract.
  5. Users won't receive any rewards and the real rewards will be locked inside the contract forever.

Tools Used

Manual Review

Recommended Mitigation Steps

We should validate stargate_ during the construction.

require(address(stargate_) == address(stakingContract_.stargate), "Wrong stargate");

Assessed type

Invalid Validation

c4-judge commented 11 months ago

thereksfour changed the severity to QA (Quality Assurance)