{"content":{"title":"GFA 攻击事件","body":"0415\r\n\r\n被攻击合约：0x278ce7151bfd1b035e8bc99e15b4d9773969d4ed\r\n\r\n交易哈希：0xe15d6f7fa891c2626819209edf2d5ded6948310eaada067b400062aa022ce718\r\n\r\n## 漏洞原因\r\n\r\n没有对合约进行权限的检查，任何人都可以更改奖励算法的参数。\r\n\r\n设置奖励参数\r\n\r\n```solidity\r\n    function setReward(\r\n        address rewardSender,\r\n        uint256 amount,\r\n        uint256 remain,\r\n        uint256 price\r\n    ) public {\r\n        if (reward[rewardSender].length == 0) {\r\n            rewardKeys.push(rewardSender);\r\n        }\r\n\r\n        reward[rewardSender].push(\r\n            RewardData(rewardSender, amount, remain, price, block.timestamp)\r\n        );\r\n        _totalRemainCnt += remain;\r\n    }\r\n```\r\n\r\n生成奖励的函数\r\n\r\n```solidity\r\nfunction generateReward(uint256 coinPrice) public \r\n                uint256 pawnPrice = reward[rewardKeys[i]][j].price;\r\n                uint256 targetRelease = reward[rewardKeys[i]][j].amount.mul(\r\n                    _mineDaliyRatio\r\n                ) / 100;\r\n                uint256 fixMineCoin = targetRelease.mul(_fixMineCoinRatio).div(\r\n                    100\r\n                );\r\n                uint256 sameCoinValue = (\r\n                    ((targetRelease - fixMineCoin) * pawnPrice).div(coinPrice)\r\n                );\r\n\r\n                uint256 release = sameCoinValue + fixMineCoin;\r\n                if (reward[rewardKeys[i]][j].remain < release) {\r\n                    release = reward[rewardKeys[i]][j].remain;\r\n                }\r\n\r\n                if (waitRelease[rewardKeys[i]] != 0) {\r\n                    waitRelease[rewardKeys[i]] += release;\r\n                }\r\n```\r\n\r\n任何用户都可以随意更改waitRelease值，而用户如果使用GFA token向GFA token合约转账时，会检查参数amount是否为10000，如果为10000将把`_tokenDistributor` 合约的金额转移给sender，sender在该过程中只需要支付10000 GFA。\r\n\r\n相关transfer部分如下\r\n\r\n```solidity\r\n    } else if (recipient == contractAddress) {\r\n      if (amount == releaseAmount) {\r\n        uint256 waitRelease = reward.getWaitReleaseCoin(sender);\r\n        uint256 poolBalance =  _balances[address(_tokenDistributor)];\r\n        if (poolBalance < waitRelease) {\r\n            waitRelease = poolBalance;\r\n        }\r\n\r\n        reward.releaseCoin(sender);\r\n        _basicTransfer(address(_tokenDistributor), sender, waitRelease);\r\n        _basicTransfer(sender, recipient, amount);\r\n```\r\n\r\n\r\n\r\n## 修复\r\n\r\n添加`setReward` 和 `generateReward` 的权限检查"},"author":{"user":"https://learnblockchain.cn/people/19673","address":"0x7bd4c4871d84ef8c8a52fac82b811d2dea5ca627"},"history":null,"timestamp":1713290516,"version":1}