合约代码地址:https://ropsten.etherscan.io/address/0x92cbCBc31f6bb209f2C4F6cbd0596ba22D71979d#code
pwn合约代码地址:https://ropsten.etherscan.io/address/0x88DF1483Db9d3720378d2CB6859c8487e4412ac7#code
function dividendsOf(address _customerAddress)
view
public
returns (uint256)
{
return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude;
}
在计算分红时如果tokenBalanceLedger_[customerAddress])为0同时payoutsTo[customerAddress]为一个很小.则分红计算的结果会变得很大。
在函数transferFromInternal中合约到人的交易中没有对合约地址payoutsTo[from] 进行操作。导致如果合约调用
if (fromLength > 0 && toLength <= 0) {
// contract to human
contractAddresses[_from] = true;
contractPayout -= (int) (_amountOfTokens);
tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens);
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens);
} else if (fromLength <= 0 && toLength > 0) {
// human to contract
contractAddresses[_toAddress] = true;
contractPayout += (int) (_amountOfTokens);
tokenSupply_ = SafeMath.sub(tokenSupply_, _amountOfTokens);
payoutsTo_[_from] -= (int256) (profitPerShare_ * _amountOfTokens);
} else if (fromLength > 0 && toLength > 0) {
// contract to contract
contractAddresses[_from] = true;
contractAddresses[_toAddress] = true;
} else {
// human to human
payoutsTo_[_from] -= (int256) (profitPerShare_ * _amountOfTokens);
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens);
}
withdraw()函数增加了payoutsTo_[]的值
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude);
同时将token清零。dividendsOf会得到(uint256(-1)-(dividends * magnitude))/magnitude为一个很大的值。通过withdraw无法提取。但通过reinvest()函数再次购买大量token影响profitPerShare 的值。再根据god合约内eth的总量计算需要卖出的token数量(myDividends-ether/Profitpershare)=tokens ,用来减小自己withdraw)的数量(因为当前withdraw数量太多合约无法提供)。最后withdraw清空合约内的eth。
合约内payoutsTo_可以轻松溢出,可能是作者故意也解释了在加减payoutsTo_时没有用safemath。主要漏洞点应该就是transferFromInternal合约与人的交易上没有修改payoutsTo_
5983

被折叠的 条评论
为什么被折叠?



