0x73696d616f / codeup-issues-external

Smart Contract and configuration scripts for codeup.app DEFI game based on Ethereum story
https://codeup.app
0 stars 0 forks source link

Total `ETH`, `WETH` and `gameETH` are not tracked which will lead to insolvency #3

Open 0x73696d616f opened 6 days ago

0x73696d616f commented 6 days ago

Description

Users may upgrade their towers so they receive gameETH over time which can later be withdrawn for ETH. However, there is no actual tracking in either of the funds, which means that eventually once users stop entering the protocol, there will not be enough ETH to pay everyone for their yield. A poc was created showing that after just 16 hours a user receives more ETH as yield than their initial deposit when buying gameETH.

Thus, initial users that upgrade their towers will just get all yield very quickly from new users, eventually making the protocol insolvent as everyone has yield to claim but nobody wants to deposit.

Another related concern is that users have no option to withdraw their gameETH, even if they have for example upgraded their towers to the max level. This essentially means that it does not make sense to ever deposit more than the max cost to upgrade all builders, and users that do so will have just wasted extra funds.

Lastly, the remaining weth balance will be impossible to withdraw because the last user that has upgraded their towers to the max builders will withdraw these funds and pay a commision to the pool in amountForPool, which will never be recovered.

Recommendation

Users not being able to always get their yield due to the contract not having enough eth is a design choice, as users need to be quick to claim their yield. However, it never makes sense to add more game eth than the amount left needed to fully upgrade their tower, so a check could be added. Additionally, a way to add as liquidity the last weth from commisions should be added.

Maxim280596 commented 5 days ago

Most likely, we won't be able to change this, this is the idea of the project, so that users try to be as fast as possible to get their part of the CodeUpERC20 token and keep it or sell it. That is why we have set a small price for the game token so that users can play with a small deposit. Some users receive the funds of users who came later, but this is just for fun, the main point is a token that will be withdrawn after completing the game. The more users, the higher the price of the token, in our opinion, it will add interest. Also, the WETH that is collected on the contract should be added to the liquidity pool only during the game, if someone sees that there is a lot of WETH on the contract and they have CodeupERC20, they can play the game from another wallet and trigger the swap and add liquidity. We don't keep any CodeupERC20 for ourselves, and we don't charge any fees for the game. If necessary, we can make a more honest replenishment format, write logic in the contract code that will mint the entire totalSupply of CodeupERC20 with the game contract address, and set the gameETH price to a constant instead of an argument.
As an option, we can add a tracking system for minutes in the game, if the user has withdrawn rewards for 1000 minutes, he will no longer be able to receive rewards. But this needs to be clarified with my CEO.

What can we do to mitigate this problem?

Maxim280596 commented 5 days ago

We can also reduce the amount of remuneration paid to users in case of withdrawals or reinvestment.

0x73696d616f commented 5 days ago

The only issue is that effectively some users will end up buying game eth that will be consumed right away by the yield of already existing users. Usually protocols ensure that the yield matches the amount of funds in the contract, so that everyone can always receive their entitled yield. In this case, it would mean adjusting the yield somehow to match the actual available funds. An example implementation would be storing the amount of commissions paid, and giving out yield according to this.

Maxim280596 commented 5 days ago

Income in ETH is an additional bonus, the main thing is to get the reward in CodeupERC20. Users will be informed about these risks, this is a game for fans only. Unfortunately, the whole system is highly risky and dependent on the arrival of new users, we understand these risks. The maximum we can do is to somehow limit the amount of rewards that users receive.

Can this issue be mitigated to the medium level?

Maxim280596 commented 5 days ago

It is a standard mechanic of high-risk ROI games.

Maxim280596 commented 5 days ago

But the moment when the contract runs out of funds is inevitable. We can only extend it by adding the inability to receive rewards if you have collected rewards for a certain amount of “min”

0x73696d616f commented 5 days ago

If the intention is to keep the design exactly as is, I think we can assume it's part of the design users will not always be able to collect their yield in case people stop depositing and this is a risk, hence we can lower the severity.

However, I believe users should not be able to deposit more than the eth amount necessary to fully upgrade their tower, as it would just be lost.

When implementing this, it may happen that some users buy game eth but already have upgraded their towers, but not fully, so the maximum deposit should be the amount left needed to upgrade their remaining towers.

I have lowered the likelihood because if we say that users not being able to claim their yield is a design choice than the part of the issue left is users being able to add excessive game eth which has a lower likelihood.

There is still the issue of the last weth never being able to be added as liquidity to the pool when the last user withdraws and pays a commission. To fix this, there could be a separate way to add liquidity.

Maxim280596 commented 5 days ago

I have added the necessary fixes, now there is a limit on the maximum purchase of gameETH, the user will not be able to buy more than necessary to complete the game.

Also, for the remaining WETH, a function was added to force the addition of liquidity, which can be called by anyone, but only a week after the previous addition of liquidity. It is necessary to prevent someone from constantly calling it.

Can we assume that this problem has been solved?

0x73696d616f commented 4 days ago

Fixed in #6020c6f.