风险提示:理性看待区块链,提高风险意识!
波场TRON-Rich团队的UsdtBank合约简介
首页 > 币界资讯 > 区块链知识 2019-05-16 13:44:09

随着波场 DApp 生态的不断发展, DApp开发者和用户的数量急速增长,经济利益的迅速累积,提高智能合约的防攻击能力,越来越成DApp 开发的一个重要考量。因此,波场面向社区,征集DApp 的开源代码,结合其合约源码,以实战的方式,讲解波场智能合约开发时,需要注意的一些安全细节。更多源码征集方式请参见附录。

本期小课堂征集到的是 TRON-Rich 团队的 UsdtBank合约。在分析合约之前的首要事情,就是通过合约验证平台,验证其为真的开源合约。接下来先用小段篇幅对社区的https://troneye.com(以下简称 TRON-Eye)进行解析,以选定合约验证平台。

合约验证的原理在于,Solidity 合约编译后的 bytecode 由可执行bytecode 以及meta-hash两部分组成,同一份合约源码在相同编译环境下多次编译,产生的 bytecode 相同,正确的合约验证方法,应该比对bytecode,从而验证源码是否和链上合约完全一致。

(TRON-Eye 的源码提交页)

TRON-Eye详细阐述了其验证思路,同时还在合约源码展示页支持用户自行编译bytecode并比对,提高了公信力。因此,我们选定 TRON-Eye 作为小课堂的验证平台,校验合约是否真正开源。

( TRON-Eye 的合约源码展示页)

图2所示的,即为本次待考察合约 ,TRON-Rich 团队的UsdtBank合约代码。接下来就对其源码,进行安全角度的详细解读。

如非必要, 应该禁止被其他合约调用

允许被其他合约调用, 容易被发起回退攻击,尤其是即时返回结果的下注类游戏。攻击合约可以在其合约函数中调用目标合约,如果目标合约立即返回结果,当攻击合约发现返回的结果对自己不利时,主动 revert,回退交易。从而实现“只赢不输”。

/*
* only human is allowed to call this contract
*/
modifier isHuman() {
require((bytes32(msg.sender)) == (bytes32(tx.origin)));
_;
}

UsdtBank 采用了上述代码,判断是否是合约,其原理就是,如果是合约调用的话,msg.sender 是外层合约地址,但是 tx.origin 是合约调用者。当然这段代码先将 address强转 bytes32,浪费了能量,建议直接采用 msg.sender == tx.origin 即可。

function invest(uint256 _referrerCode, uint256 _planId, uint256 _value) 
public whenNotPaused isHuman {
if (_invest(msg.sender, _planId, _referrerCode, _value)) {
emit onInvest(msg.sender, _value);
}}

判断一个地址是否是合约地址

下面是 UsdtBank 使用这个modifier 的方式,可以发现,这个 modifier 仅适合用来限制被调用方是普通用户。那么如果需要判断某个传入的address 参数是人,而不是合约,则需要使用另外一种方式。

function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}

Q: 那么为什么 isHuman() 这个 modifier 不使用这种方式呢?

A: 这是因为,通过 extcodesize 方式判断一个地址是否是合约地址,并不准确。当在其他合约的构造函数中读取extcodesize时,这个值总是0.

More: 波场已经提交了一个关于增加 address.type 的 TIP,可以直观准确的判断一个地址类型,欢迎参与该 TIP 的讨论。

小结论:要想完整限制合约中的调用者,以及合约中的地址参数为 Human,目前最好的方式,是结合前述的 isHuman() modifier 以及 isContract().

怎么通过合约,处理TRC20的转账

本期选择 UsdtBank 讲解的一个重要原因是,UsdtBank 是一个支持 USDT参与投注的合约,有助于推广使用TRC20投注游戏合约的正确姿势。

UsdtBank 和 USDT 投注相关的有如下一些代码:

ITRC20publicusdtAddr_;
function setUsdtAddr(address _usdtAddr) public onlyOwner {
require(address(usdtAddr_) == address(0x00));
require(address(_usdtAddr) != address(0x00));
usdtAddr_ = ITRC20(_usdtAddr);
}

上述代码表示,usdtAddress 仅允许初始化的时候,设置一次(谢绝跑路 ^_^)。

function _invest(address _addr, uint256 _planId, uint256 _referrerCode, 
uint256 _amount)
private
notContract(_addr)
returns (bool)
{
usdtAddr_.transferFrom(_addr, address(this), _amount);
….
}

由于 TRC20 token 相对 TRX以及 TRC10 token 最大的区别在于,TRX 和 TRC10的balance存储于address 的 account 中,而 TRC20 token 的 balance存储在 TRC20合约里。直接调用 TRC20合约的 transfer 函数,虽然能够将自己的余额转到另外一个地址名下,但事实上只是在 TRC20合约里发生了两者balance 字段值的修改。所以采用 标准TRC20下注,必须使用 Approve 和 TransferFrom 两步分开的方式。虽然这会导致用户签名两次。


上一篇: 数字货币的多重签名机制能否保证资产安全?
下一篇: 数字货币K线形态图解:头肩底买入形态!
推荐专栏
web3首席知识博主
一位相信价值投资的币圈KOL。稳定盈利的缠论野生交易员 #BTC行情分析师 #价值投资 #链上数据分析
爱Web 3,爱生活,爱科技,爱炒币的老韭菜
热门币种
更多
币种
价格
24H涨跌幅
BTC比特币
¥265,902.86
37,256.43 USDT
+0.45%
ETH以太坊
¥14,471.18
2,027.60 USDT
+0.17%
USDT泰达币
¥7.20
1.01 USDT
-0.01%
BNB币安币
¥1,630.32
228.43 USDT
+0.63%
XRP瑞波币
¥4.36
0.61070 USDT
+1.51%
USDC
¥7.14
1.00 USDT
+0.03%
SOLSolana
¥400.57
56.13 USDT
+1.81%
ADA艾达币
¥2.70
0.37780 USDT
-1.02%
OKBOK币
¥399.11
55.92 USDT
-0.14%
DOGE狗狗币
¥0.55680
0.07802 USDT
-0.83%
热搜币种
更多
币种
价格
24H涨跌幅
Terra Classic
¥0.00
9.625E-5 USDT
-19.02%
Gala
¥0.18
0.025524 USDT
-5.1%
dYdX
¥22.72
3.2118 USDT
-0.29%
比特股
¥0.05
0.006515 USDT
-3.81%
PancakeSwap
¥15.64
2.2106 USDT
-2.19%
Conflux
¥1.09
0.1537 USDT
-1.91%
Filecoin
¥31.61
4.4688 USDT
-0.15%
FTX Token
¥29.39
4.1548 USDT
+15.8%
Yield Guild Games
¥2.56
0.3619 USDT
-0.44%
Shiba Inu
¥0.00
8.16E-6 USDT
-1.81%
比特币
¥263,550.12
37256.43 USDT
+0.45%
波场
¥0.72
0.102 USDT
-2.58%
最新快讯
更多
汇款公司Kalyssi旗下钱包已集成AlchemyPay法币出入金解决方案
2023-11-28 19:26:47
汇丰、恒生、渣打、富邦华一四家外资银行入围首批“数字人民币”业务试点名单
2023-11-28 19:06:57
摩根大通和Apollo计划建立代币化“企业主网”
2023-11-28 19:03:57
Nansen2公测版本上线,新增链上数据异动、智能搜索等功能
2023-11-28 18:59:52
西班牙公民需在明年3月底前申报其海外平台上加密货币持仓
2023-11-28 18:53:43
Nansen2已公开测试
2023-11-28 18:53:38
dYdX基金会:主网启动以来超过1645万DYDX被质押
2023-11-28 18:52:07
下载币界网APP