幻想通过套利脚本躺着赚钱的懵懂青年竟然遭遇上了庞氏骗局
前情提要
一个月总有那么二十几天不想努力了,于是乎心心念念想去搞个套利脚本,那样他就可以自动套利,从此走上财富自由的人生道路。啊!话不多说直接开干,立马在开始在谷歌上搜索致富秘诀,我可劲儿搜,在谷歌前列就看到了一篇文章( 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
, Deposit
和 Player
三个结构体,啊这玩意不重要,过。
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 的这浑水的时候能够留个心眼,啊坏人很多的,都觊觎这你手里的这点银两呢。