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


    前情提要

    一个月总有那么二十几天不想努力了,于是乎心心念念想去搞个套利脚本,那样他就可以自动套利,从此走上财富自由的人生道路。啊!话不多说直接开干,立马在开始在谷歌上搜索致富秘诀,我可劲儿搜,在谷歌前列就看到了一篇文章( 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 的这浑水的时候能够留个心眼,啊坏人很多的,都觊觎这你手里的这点银两呢。


    __EOF__

  • 本文作者: 阿菜种菜的菜园子
  • 本文链接: https://www.cnblogs.com/ACaiGarden/p/16484341.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    教你批量将视频画面顺时针旋转90度
    【数值计算】追赶法
    多进程编程
    最优链表&&链表与顺序表的优缺点.
    Java Map.put()有什么功能呢?(添加集合)
    常见工具指令【Vim | GIT | ZIP | UNZIP | IDEA】
    如何实现办公自动化?
    python学习 6.15
    python添加命令行参数
    Channel
  • 原文地址:https://www.cnblogs.com/ACaiGarden/p/16484341.html