内容简介:近日,听说以太坊上的泰达币(USDT)频繁被增发。本着学习的目的在以下是 TetherToken 智能合约的 USDT 增发函数:可以看到增发 USDT 需要 TetherToken 合约的 owner 账户调用 issue(uint) 增发函数进行,增发成功后还会抛出 Issue(amount) 增发事件。
ERC-20 USDT 代币增发分析
近日,听说以太坊上的泰达币(USDT)频繁被增发。本着学习的目的在 etherscan 上审计了泰达币的智能合约(TetherToken)源码以及 USDT 增发相关的调用事件,本文记录一下分析过程。
以下是 TetherToken 智能合约的 USDT 增发函数:
// Issue a new amount of tokens // these tokens are deposited into the owner address // // @param _amount Number of tokens to be issued function issue(uint amount) public onlyOwner { // 确保增发后不会溢出 require(_totalSupply + amount > _totalSupply); require(balances[owner] + amount > balances[owner]); // 增发到 owner 账户 balances[owner] += amount; _totalSupply += amount; // 发送增发事件 Issue(amount); }
可以看到增发 USDT 需要 TetherToken 合约的 owner 账户调用 issue(uint) 增发函数进行,增发成功后还会抛出 Issue(amount) 增发事件。
再看下最近的 增发记录 截图:
Transaction Hash:0xdd108cd36fbeaab03b29ac46d465ad9824618d683268681d3206bd78302e0d71
可以看到在上图交易详情中并没有调用 TetherToken 合约的 issue(uint) 增发函数,而是调用了 MultiSigWallet 合约的 confirmTransaction(uint) 函数完成的增发操作。
需要注意以下两点:
1、Bitfinex: MultiSig 2 是 MultiSigWallet 合约的别称 2、Bitfinex: MultiSig 2 是 TetherToken 合约的 owner 地址
TetherToken 合约调用分析
我们先看看 MultiSigWallet 合约的 confirmTransaction(uint) 函数的实现
/// @dev Allows an owner to confirm a transaction. /// @param transactionId Transaction ID. function confirmTransaction(uint transactionId) public ownerExists(msg.sender)// 确保当前调用者具备 owner 权限 transactionExists(transactionId)// 确保 submitTransaction(address,uint,bytes) 函数被调用 notConfirmed(transactionId, msg.sender)// 确保当前调用者没有确认过该交易 { confirmations[transactionId][msg.sender] = true;// 当前调用者确认该交易 Confirmation(msg.sender, transactionId);// 发送确认事件 executeTransaction(transactionId); } /// @dev Allows anyone to execute a confirmed transaction. /// @param transactionId Transaction ID. function executeTransaction(uint transactionId) public notExecuted(transactionId)// 确保该交易没有被执行 { if (isConfirmed(transactionId)) {// 检查该交易是否满足指定个 owner 的确认(目前是 3 个) Transaction tx = transactions[transactionId];// 根据 ID 取出相应的交易事务 tx.executed = true;// 修改该交易执行状态 if (tx.destination.call.value(tx.value)(tx.data))// 跨合约调用 Execution(transactionId);// 发送执行成功事件 else { ExecutionFailure(transactionId); tx.executed = false; } } }
调用 confirmTransaction(uint) 函数确认并执行交易需要满足以下条件
1、当前调用者具备 owner 权限。 2、当前交易已被提交,既调用了 submitTransaction(address,uint,bytes) 函数。 3、当前交易已被 3 个 owner 确认。
submitTransaction(address,uint,bytes) 会调用到合约内部的 addTransaction(address,uint,bytes) 函数,其实现如下:
/* * Internal functions */ /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet. /// @param destination Transaction target address. /// @param value Transaction ether value. /// @param data Transaction data payload. /// @return Returns transaction ID. function addTransaction(address destination, uint value, bytes data) internal notNull(destination)// 确保非 0x0 地址 returns (uint transactionId) { transactionId = transactionCount; transactions[transactionId] = Transaction({// 添加交易事务 destination: destination, value: value, data: data, executed: false }); transactionCount += 1; Submission(transactionId);// 发送提交事件 }
最终一次完整的 提交 -> 确认 操作流程如下:
1、调用 submitTransaction(address,uint,bytes) 函数提交事务并传入参数:contract-address、eth-value、payload。 注意:提交事务包含一次事务确认。
依次发送 Submission 事件 -> Confirmation 事件。
2、调用 confirmTransaction(uint) 确认并执行事务,需要 3 个不同的 owner 账户完成最终的确认。
依次发送 Confirmation 事件 -> 执行 payload 所产生的事件(满足确认数量)-> Execution 事件。
TetherToken 跨合约调用如下图所示:
USDT 增发分析
继续看 这笔 增发交易的调用事件,正好满足调用 confirmTransaction(uint) 函数所产生的事件。
通过查询 transactionId 即可看到调用参数
转换成以下伪代码:
0xdAC17F958D2ee523a2206206994597C13D831ec7.call.value(0)( bytes4(keccak256("transfer( 0x5754284f345afc66a98fbb0a0afe71e0f007b949,120000000000000)")) )
那么 Bitfinex: MultiSig 2 地址的 USDT 是哪来的呢?根据 transactionId 继续向前追踪一个事务即可找到真正为 Bitfinex: MultiSig 2 地址增发 USDT 的交易:
转换成以下伪代码:
0xdAC17F958D2ee523a2206206994597C13D831ec7.call.value(0)( bytes4(keccak256("issue(120000000000000)")) )
Transaction Hash:0xb467ea92b5c0095b1a96f35eb466b239c13e5b0b3f493e3e452f832d99830d6b
这才是真正为 Bitfinex: MultiSig 2 地址增发 USDT 的操作。
USDT 增发如下图所示:
总结
可以看到,USDT 的增发需要通过 MultiSigWallet 跨合约调用才能完成。而 MultiSigWallet 智能合约存在多个 owner 用户,完成一次跨合约调用需要至少 3 个 owner 的确认。这种增发机制在一定程度上杜绝了当某一 owner 账户丢失或被盗时 USDT 被恶意增发的安全隐患。
*本文作者:北京链安安全实验室,转载请注明来自FreeBuf.COM
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 金色荐读 | 印钞机的秘密:USDT增发最全技术细节披露
- 使用动态分析技术分析 Java
- 使用动态分析技术分析 Java
- 案例分析:如何进行需求分析?
- 深度分析ConcurrentHashMap原理分析
- 如何分析“数据分析师”的岗位?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java数据结构和算法
拉佛 / 计晓云 / 中国电力出版社 / 2004-02-01 / 55.00元
《Java数据结构和算法》(第2版)以一种易懂的方式教授如何安排和操纵数据的问题,其中不乏一些难题:了解这些知识以期使计算机的应用获得最好的表现。不管使用何种语言或平台,掌握了数据结构和算法将改进程序的质量和性能。 《Java数据结构和算法》(第2版)提供了一套独创的可视讨论专题用以阐明主要的论题:它使用Java语言说明重要的概念,而避免了C/C++语言的复杂性,以便集中精力论述数据结构和算法。经......一起来看看 《Java数据结构和算法》 这本书的介绍吧!