幻想通过套利脚本躺着赚钱的懵懂青年竟然遭遇上了庞氏骗局

前情提要

一个月总有那么二十几天不想努力了,于是乎心心念念想去搞个套利脚本,那样他就可以自动套利,从此走上财富自由的人生道路。啊!话不多说直接开干,立马在开始在谷歌上搜索致富秘诀,我可劲儿搜,在谷歌前列就看到了一篇文章( BNB Train Brings World’s first EVM Arbitrage Dapp on Binance Smart Chain ),它在给一个叫 BNB Train 的项目做推广,简单说就是他做了个套利 DAPP,你把钱给他,他帮你套利。

我的愿望就要实现了?!美妙人生我来啦!

于是乎我迫不及待地打开了它的官网,开始我的危险的致富之路。

相关信息

BNB Train 官网:https://bnbtrain.ognius.com/

官网所提供的合约地址:https://bscscan.com/address/0xEa9068C2ECa022A0D0133903D905FA2F4112ae77

一打开官网呀他就主动弹我的小狐狸,一看就很迫不及待的样子。看来是等我这个知音等了很久了,等不及了都。但是我们不急,先不要输密码,先看看再说。保持优雅,不要着急,即使你很急,但是你别急。

合约分析

废话不多说,先康康合约,啊只有一个合约文件,短短的 208 行。

首先看一下,合约版本 >= 0.8.0,没有溢出风险,然后就是 Plan, DepositPlayer 三个结构体,啊这玩意不重要,过。

pragma solidity >=0.8.0;

struct Plan {
  uint8 plan_days;
  uint8 percent;
}

struct Deposit {
  uint8 plan;
  uint256 amount;
  uint40 time;
}

struct Player {
  address upline;
  uint256 dividends;
  uint256 match_bonus;
  uint40 last_payout;
  uint256 total_invested;
  uint256 total_withdrawn;
  uint256 total_match_bonus;
  Deposit[] deposits;
  uint256[5] structure; 
}

然后就是一些合约的全局变量和 event ,随便康康。

contract BNBTrain {
    address public owner;

    uint256 public invested;
    uint256 public withdrawn;
    uint256 public match_bonus;
    
    uint8 constant BONUS_LINES_COUNT = 5;
    uint16 constant PERCENT_DIVIDER = 1000; 
    uint8[BONUS_LINES_COUNT] public ref_bonuses = [50, 30, 20, 10, 5]; 

    mapping(uint8 => Plan) public plans;
    mapping(address => Player) public players;

    event Upline(address indexed addr, address indexed upline, uint256 bonus);
    event NewDeposit(address indexed addr, uint256 amount, uint8 plan);
    event MatchPayout(address indexed addr, address indexed from, uint256 amount);
    event Withdraw(address indexed addr, uint256 amount);
    
    ...
    
 }

构造函数,设定一下 万恶的 owner 以及利率。哦哟好奇怪的噢,你这个套利脚本定的还是固定利率的噢,搞得这么自信的嗷。

constructor() {
	owner = msg.sender;
	uint8 planPercent = 119;
	for (uint8 duration = 7; duration <= 30; duration++) {
		plans[duration] = Plan(duration, planPercent);
		planPercent += 5;
	}
}

然后我开始着急了,这么高的利率,存款函数在哪里,我要给你打钱,实现我的梦想,快,我已经迫不及待了,躺着赚钱的生活在向我招手,我已经想好在哪里买房了。

传入你想存的计划id _plan ,上线(推荐人)地址 _upline ,每次最少存入 0.01 BNB。

然后 payable(owner).transfer(msg.value / 10); 嗯?我刚存进来的钱你就要拿走十分之一?这不得是赚了钱以后你才从利润中扣点么,哪有上来就把我本金给扣了的,有点不对劲了。

function deposit(uint8 _plan, address _upline) external payable {
  	require(plans[_plan].plan_days > 0, "Plan not found");
  	require(msg.value >= 0.01 ether, "Minimum deposit amount is 0.01 BNB");
	
  	Player storage player = players[msg.sender];

  	require(player.deposits.length < 100, "Max 100 deposits per address");
	
  	// 更新你的上线相关的信息,我只关心我自己,不管他
  	_setUpline(msg.sender, _upline, msg.value);

  	player.deposits.push(Deposit({
    	plan: _plan,
    	amount: msg.value,
    	time: uint40(block.timestamp)
  	}));

  	player.total_invested += msg.value;
  	invested += msg.value;
	
  	// 也还是处理你上线的函数,不重要,一点也不重要
  	_refPayout(msg.sender, msg.value);

  	payable(owner).transfer(msg.value / 10);

  	emit NewDeposit(msg.sender, msg.value, _plan);
}

那看完存钱,再看看取钱的情况呗,大丈夫能存能取。_payout 函数先更新一下你连本带利能取多少钱。然后合约再从余额中把你应得的钱打给你。诶慢着,还记得我们调用 despoit 函数存钱的时候 owenr 扣了我们 10% 的本金吗?直接取是余额不够的,那么接下我们来看一下他的套利逻辑,看看它是如何赚钱的吧!

function withdraw() external {
    Player storage player = players[msg.sender];

    _payout(msg.sender);

    require(player.dividends > 0 || player.match_bonus > 0, "Zero amount");

    uint256 amount = player.dividends + player.match_bonus;

    player.dividends = 0;
    player.match_bonus = 0;
    player.total_withdrawn += amount;
    withdrawn += amount;

    payable(msg.sender).transfer(amount);

    emit Withdraw(msg.sender, amount);
}

function _payout(address _addr) private {
    uint256 payout = this.payoutOf(_addr);

    if(payout > 0) {
        players[_addr].last_payout = uint40(block.timestamp);
        players[_addr].dividends += payout;
    }
}

function _refPayout(address _addr, uint256 _amount) private {
  	address up = players[_addr].upline;

    for(uint8 i = 0; i < ref_bonuses.length; i++) {
        if(up == address(0)) break;

        uint256 bonus = _amount * ref_bonuses[i] / PERCENT_DIVIDER;

        players[up].match_bonus += bonus;
        players[up].total_match_bonus += bonus;

        match_bonus += bonus;

        emit MatchPayout(up, _addr, bonus);

        up = players[up].upline;
    }
}

啊,啊哈!很可惜200行代码已经被我们分析的差不多了,合约中好像没有,或者说压根就没打算准备套利的功能!上当了!这下子上了个大当了!什么躺着赚钱,都成泡沫,什么美好生活,刹那烟火。

这个合约做得呢,就是一个庞氏骗局。每进来一个人, owenr 就从他身上薅一笔(10%)。你要是能够拉到人进来做你的下线呢,就给你点奖励。后面来的人越来越多,那么先加入的人就可以套利成功,拿着自己的本金与利息成功离场。然后,后入场的人,就要靠后后入场人的钱来补这个窟窿,一直传下去。

啊那我们可以回过头来看一下之前被我们忽略掉的一些函数,关于上线的 _setUpline 函数,关于拉人头分成的 _refPayout 函数,在这里就不详细赘述了,梦想都破灭了还分析啥呀分析

function _setUpline(address _addr, address _upline, uint256 _amount) private {
    if(players[_addr].upline == address(0) && _addr != owner) {
        if(players[_upline].deposits.length == 0) {
          	_upline = owner;
        }

        players[_addr].upline = _upline;

        emit Upline(_addr, _upline, _amount / 100);

        for(uint8 i = 0; i < BONUS_LINES_COUNT; i++) {
          	players[_upline].structure[i]++;

          	_upline = players[_upline].upline;

          	if(_upline == address(0)) break;
        }
    }
}

function _refPayout(address _addr, uint256 _amount) private {
    address up = players[_addr].upline;

    for(uint8 i = 0; i < ref_bonuses.length; i++) {
        if(up == address(0)) break;

        uint256 bonus = _amount * ref_bonuses[i] / PERCENT_DIVIDER;

        players[up].match_bonus += bonus;
        players[up].total_match_bonus += bonus;

        match_bonus += bonus;

        emit MatchPayout(up, _addr, bonus);

        up = players[up].upline;
    }
}

后记

官网拉到最下面还标了一个 Verified by BSC Scan 的字样,也确实是上传了自己的代码嗷,即使是用套利作为羊头骗骗你的。

怎么说,幻想破灭了,再琢磨琢磨点别的呗。然后也希望大家在趟各种 DeFi 的这浑水的时候能够留个心眼,啊坏人很多的,都觊觎这你手里的这点银两呢。

posted @ 2022-07-16 15:27  ACai_sec  阅读(312)  评论(0编辑  收藏  举报