Ethereum Credit Guild - 0xdice91's results

A trust minimized pooled lending protocol.

General Information

Platform: Code4rena

Start Date: 11/12/2023

Pot Size: $90,500 USDC

Total HM: 29

Participants: 127

Period: 17 days

Judge: TrungOre

Total Solo HM: 4

Id: 310

League: ETH

Ethereum Credit Guild

Findings Distribution

Researcher Performance

Rank: 127/127

Findings: 1

Award: $3.05

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

3.0466 USDC - $3.05

Labels

bug
3 (High Risk)
satisfactory
sufficient quality report
duplicate-473

External Links

Lines of code

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/2376d9af792584e3d15ec9c32578daa33bb56b43/src/loan/SurplusGuildMinter.sol#L216-L290 https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/2376d9af792584e3d15ec9c32578daa33bb56b43/src/loan/SurplusGuildMinter.sol#L228-L231 https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/2376d9af792584e3d15ec9c32578daa33bb56b43/src/loan/SurplusGuildMinter.sol#L274-L284

Vulnerability details

In SurplusGuildMinter.sol getRewards() is used to get rewards from a staking position, the variable userStake is first declared to reserve memory to hold a UserStake struct when the function is called, but the variable has not been initialised yet. The variable is only initialised further down in the function

userStake = _stakes[user][term];

The issue here is that the variable userStake is used to determine if the user has been slashed or not before it has been initialised leading to its components being in their default values

        lastGaugeLoss = GuildToken(guild).lastGaugeLoss(term);
        if (lastGaugeLoss > uint256(userStake.lastGaugeLoss)) {
            slashed = true;
        }

As userStake.lastGaugeLoss still has its default value of 0, if the term has ever suffered a loss in the past even before the user staked, the check will always return true (that is slashed will be set to true).

Impact

As a result of this error, Users guildReward and their staked first loss capital (credit token) will be unfairly slashed and lost forever whenever getRewards() is called.

            if (slashed) {
                guildReward = 0;
            }
        if (slashed) {
            emit Unstake(block.timestamp, term, uint256(userStake.credit));
            userStake = UserStake({
                stakeTime: uint48(0),
                lastGaugeLoss: uint48(0),
                profitIndex: uint160(0),
                credit: uint128(0),
                guild: uint128(0)
            });
            updateState = true;
        }

Tools Used

Manual Review

The UserStake memory userStake variable should simply be initialised first with the user values before the check for if the user has been slashed is done.

    function getRewards(
        address user,
        address term
    )
        public
        returns (
            uint256 lastGaugeLoss, // GuildToken.lastGaugeLoss(term)
            UserStake memory userStake, // stake state after execution of getRewards()
            bool slashed // true if the user has been slashed
        )
    {
        bool updateState;
        userStake = _stakes[user][term]; // The initialisation should be moved there before the check for if slashed 
        lastGaugeLoss = GuildToken(guild).lastGaugeLoss(term);
        if (lastGaugeLoss > uint256(userStake.lastGaugeLoss)) {
            slashed = true;
        }


        // if the user is not staking, do nothing
       
        if (userStake.stakeTime == 0)
            return (lastGaugeLoss, userStake, slashed);

//More code

}

Assessed type

Invalid Validation

#0 - c4-pre-sort

2023-12-29T14:38:12Z

0xSorryNotSorry marked the issue as sufficient quality report

#1 - c4-pre-sort

2023-12-29T14:38:18Z

0xSorryNotSorry marked the issue as duplicate of #1164

#2 - c4-judge

2024-01-28T20:13:37Z

Trumpero marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter