This document is a security audit report performed by RideSolo, where USDT Token has been reviewed.
4 issues were reported:
- 3 low severity issues.
- 1 owner privileges.
- Pause/unpause
transferandtransferFrom. - Blacklist users addresses individualy from using
transferandtransferFromthroughaddBlackListandremoveBlackList. - Burn blacklisted users assets (please note that the assets are supposed to be backed in a 1:1 ratio) using
destroyBlackFundsfunction. - A maximal fee percentage of 20/10000 can be applied per transaction with a maximal value of 50 USDT, check here.
transfer and transferFrom allow the destination address to be equal to zero, meaning that users fund can be lost if sent to it by mistake.
function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
uint fee = (_value.mul(basisPointsRate)).div(10000);
if (fee > maximumFee) {
fee = maximumFee;
}
uint sendAmount = _value.sub(fee);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(sendAmount);
if (fee > 0) {
balances[owner] = balances[owner].add(fee);
Transfer(msg.sender, owner, fee);
}
Transfer(msg.sender, _to, sendAmount);
}
function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) {
var _allowance = allowed[_from][msg.sender];
uint fee = (_value.mul(basisPointsRate)).div(10000);
if (fee > maximumFee) {
fee = maximumFee;
}
if (_allowance < MAX_UINT) {
allowed[_from][msg.sender] = _allowance.sub(_value);
}
uint sendAmount = _value.sub(fee);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(sendAmount);
if (fee > 0) {
balances[owner] = balances[owner].add(fee);
Transfer(_from, owner, fee);
}
Transfer(_from, _to, sendAmount);
}
When issuing or redeeming tokens a transfer event should be emitted back and forth to address(0). ERC20 standard: "A token contract which creates new tokens SHOULD trigger a Transfer event with the _from address set to 0x0 when tokens are created". the same can be deducted when redeeming or burning tokens.
Same isssue is applicable for TetherToken constructor.
https://gist.github.com/RideSolo/24c79eb34b565ade477ec89c2af49a5b#file-usdt-sol-L406
https://gist.github.com/RideSolo/24c79eb34b565ade477ec89c2af49a5b#file-usdt-sol-L420
- It is possible to double withdrawal attack. More details here
- Lack of transaction handling mechanism issue. WARNING! This is a very common issue and it already caused millions of dollars losses for lots of token users! More details here
Add into the function transfer(address _to, ... ) and transferFrom the following code, to avoid transfers to the contract address:
require( _to != address(this) );
The audited code is safe, but etherem USDT holders should be aware of the owner privileges described in issue 3.1.
nice