TangYuanSwap security record

BNB Chaintangyuan.ink

As of 3 Nov 2026, TangYuanSwap has 1 audit report on Trustblock, by CertiK, dated 31 Jan 2024. That report lists no open critical findings. It also holds 1 deployed contract on 1 chain.

Critical findings
No open critical findings
In 1 report.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.

Audits1

Newest first

AuditSecurity firmDateScopeCritical findingsReport
TangYuan-AuditSecurity firm: CertiKDate: Scope: 1 address on BNB ChainNo open critical findingsOriginal removed

Findings19

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High401
Medium700
Low700
HighCentralized Token Holding Position RiskTangYuan-Audit · CertiK · 31 Jan 2024Open

In the contract **MktCap**, tokens are gradually swapped to WBNB and then centralized into the `marketingAddress` EOA address(es) over time. This creates a severe centralization risk and can lead to manipulation of the tokenomics of the project. ```solidity if (amount2Marketing > 0) { uint cake; for (uint i = 0; i < marketingAddress.length; i++) { cake = amount2Marketing.mul(marketingShare[i]).div(sharetotal); IERC20(token1).transfer(marketingAddress[i], cake); } } ``` Normally a higher portion of the charged fees will be used to add liquidity to the pool to maintain the liquidity of the project. However, Tokens are constantly swapped to WBNB and transferred to the `marketingAddress`, causing price drops over time. ```solidity markting : 29 burn : 0 addL : 1 total : 30 ```

Open the report
HighInitial Token DistributionTangYuan-Audit · CertiK · 31 Jan 2024Open

All of the TangYuan tokens are sent to the contract deployer's externally-owned account (EOA) addresses. This is a centralization risk because the deployer can distribute tokens without obtaining the consensus of the community. Any compromise to these addresses may allow a hacker to steal and sell tokens on the market, resulting in severe damage to the project.

Open the report
HighLack of Validation In The `recoverERC20()` FunctiTangYuan-Audit · CertiK · 31 Jan 2024Open

Normally the function `recoverERC20(address token,uint amount)` is used to withdraw stuck tokens. However, in the contract `Token`, the owner can call `recoverERC20()` to transfer any ERC20 tokens from the Token contract including `TangYuan` tokens.

Open the report
HighUsers cannot transfer tokensTangYuan-Audit · CertiK · 31 Jan 2024Open

In the `_beforeTokenTransfer()`, when the function `getStatus()` returns true, the function `_transfer` will be reverted. ```solidity if(getStatus(from,to)){ revert InStatusError(from); } ``` In the `getStatus()` function, there are two cases to return true. ```solidity function getStatus(address from,address to) internal view returns(bool){ ... if(exFees[from]==1||exFees[from]==3) return true; if(exFees[to]==2||exFees[to]==3) return true; ... } ``` There is no context or documentation to understand what the (1,2,3) stands for. However, the owner can use the `setExFees()` function to set specific users to (1,2,3). Hence these users cannot transfer their tokens anymore.

Open the report
MediumFunction Calls User-Provided Addresses with no AcTangYuan-Audit · CertiK · 31 Jan 2024Open

Calling a user provided address is dangerous, especially in a public function with no access control restriction. An attacker could deploy a malicious contract and use the vulnerable function to trigger a call to the malicious contract, potentially stealing user funds or causing other serious damages. ```solidity function recoverERC20(address token,uint amount) public { if(token==address(0)){ (bool success,)=payable(dev).call{value:amount}(""); require(success, "transfer failed"); } else IERC20(token).transfer(dev,amount); //CertiK: token address is passed by parameter and the attacker can deploy a malicious token contract } ```

Open the report
MediumIncorrect token balanceTangYuan-Audit · CertiK · 31 Jan 2024Open

When an address does not have any tokens, `balanceOf(address)` will return 1 instead of 0.

Open the report
MediumLack of reasonable boundaryTangYuan-Audit · CertiK · 31 Jan 2024Open

In the function `setFees()`, the `buy`,`sell` and `transfer` will be set by the parameter and it can be close to or bigger than the `total`. ```solidity struct Fees{ uint buy; uint sell; uint transfer; uint total; } function setFees(Fees calldata fees_) public onlyOwner{ fees=fees_; } ``` Hence the `feeAmount` can be close to or bigger than the `amount`. ```solidity uint fee=ispair[from]?fees.buy:ispair[to]?fees.sell:fees.transfer; uint feeAmount= amount.mul(fee).div(fees.total); ```

Open the report
MediumPotential flashloan attack due to reliance on a sTangYuan-Audit · CertiK · 31 Jan 2024Open

The contract's reliance on a single Dex pair for price feeds in the `getToken0Price` and `getToken1Price` functions exposes it to flashloan attack risks. An attacker can use a flashloan as the initial funds for an exploit to enlarge the profit or manipulate the token price in decentralized exchanges.

Open the report
MediumPotential Out-of-Gas ExceptionTangYuan-Audit · CertiK · 31 Jan 2024Open

We also noticed that there are some transactions that has reverted on chain. https://bscscan.com/txs?a=0x683e9dcf085e5efcc7925858aace94d4b8882024&f=1. Most of them are because of out of gas exception. It seems that function `trigger()` has consumed too much gas.

Open the report
MediumPotential Sandwich AttackTangYuan-Audit · CertiK · 31 Jan 2024Open

In a front-running attack, an attacker identifies a pending transaction on the public blockchain and jumps ahead of it (typically by paying higher gas fees). A sandwich attack is a specialized form of front-running. In this scenario, attackers identify users making token swaps or adding liquidity without appropriate slippage limits. The attacker then profits by buying the asset before the victim's transaction and selling it immediately afterwards. The following functions are called without setting restrictions on slippage or minimum output amount, so transactions triggering these functions are vulnerable to sandwich attacks, especially when the input amount(`maxSell` in this case) is large: - `swapExactTokensForETHSupportingFeeOnTransferTokens()` - `swapExactTokensForETHSupportingFeeOnTransferTokens()` ```solidity=113 router.swapExactTokensForTokensSupportingFeeOnTransferTokens( amount0In, 0, path, address(_tokenDistributor), block.timestamp ); ``` Function `MktCap._sell` invokes `IRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens` without setting restrictions on slippage or minimum output amount. --- ```solidity=143 router.addLiquidity( token0, token1, amount0, amount1, 0, 0, dev, block.timestamp ); ``` Function `MktCap._addL` invokes `IRouter.addLiquidity` without setting restrictions on slippage or minimum output amount.

Open the report
Show 8 more
MediumsetPair should not be used standaloneTangYuan-Audit · CertiK · 31 Jan 2024Open

The function Token.setPairs() is used to set the mapping ispair, which means multiple pairs can be registered. This function can be used by the owner and can be used standalone. The function MktCap.setPair() is used to set `MktCap.token1` and `MktCap.pair`. The `MktCap.pair` is the only one marketing pair for the token. This function cannot be used by the owner to change the marketing pair standalone after the project starts. The only correct way is to call the `start()` function which will call the setPairs and setPair together. ```solidity function start(address baseToken,Fees calldata fees_) public onlyOwner{ setPairs(baseToken); setPair(baseToken); setFees(fees_); } ``` Secondly, addresses are not validated before assignment or external calls, potentially allowing the use of zero addresses and leading to unexpected behavior or vulnerabilities. ```solidity function setPair(address token) public onlyOwner { token1 = token; _tokenDistributor = new TokenDistributor(token1); IERC20(token1).approve(address(router), uint(2 ** 256 - 1)); pair = IFactory(router.factory()).getPair(token0, token1); } ``` --- `token` is not zero-checked before being used.

Open the report
LowCostly Operation Inside LoopTangYuan-Audit · CertiK · 31 Jan 2024Open

Reading, initializing, and modifying storage variables cost more gas than operating local variables, and this gas cost can significantly increase when these operations are performed inside a loop. Reference: https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack [internal use only: e.g., https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop] ```solidity=122 ktNum = ktNum+1; ``` --- ```solidity=124 ktNum = ktNum+1; ```

Open the report
LowPotential Divide by ZeroTangYuan-Audit · CertiK · 31 Jan 2024Open

Performing division by zero would raise an error and revert the transaction. ```solidity=161 uint toBurn = amount.mul(allot.burn).div(allot.total); ``` The expression `amount.mul(allot.burn).div(allot.total)` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=162 uint toAddL = amount.mul(allot.addL).div(allot.total).div(2); ``` The expression `amount.mul(allot.addL).div(allot.total)` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=171 IERC20(token0).totalSupply().mul(autoSell.minPart).div( autoSell.parts ) ``` The expression `IERC20(token0).totalSupply().mul(autoSell.minPart).div(autoSell.parts)` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=175 uint maxSell = IERC20(token0).totalSupply().mul(autoSell.maxPart).div( autoSell.parts ); ``` The expression `IERC20(token0).totalSupply().mul(autoSell.maxPart).div(autoSell.parts)` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=185 uint amount2AddL = amount2.mul(allot.addL).div(total2Fee).div(2); ``` The expression `amount2.mul(allot.addL).div(total2Fee)` may divide by zero. Its divisor has has estimated interval [-173688133855974293135356477513031861779904976998460846059186376011869694459902, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=191 cake = amount2Marketing.mul(marketingShare[i]).div(sharetotal); ``` The expression `amount2Marketing.mul(marketingShare[i]).div(sharetotal)` may divide by zero. Its divisor has has estimated interval [0, 231584178474632390847141970017375815706539969331281128078915168015826259279870]. --- ```solidity=79 uint feeAmount= amount.mul(fee).div(fees.total); ``` The expression `amount.mul(fee).div(fees.total)` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935]. --- ```solidity=121 _receiveD = address(MAXADD/ktNum); ``` The expression `MAXADD / ktNum` may divide by zero. Its divisor has has estimated interval [0, 1461501637330902918203684832716283019655932542979].

Open the report
LowPull-Over-Push Pattern In `transferOwnership()` FTangYuan-Audit · CertiK · 31 Jan 2024Open

The change of `_owner` by function `transferOwnership()` overrides the previously set `_owner` with the new one without guaranteeing the new `_owner` is able to actuate transactions on-chain.

Open the report
LowRedundant Code ComponentsTangYuan-Audit · CertiK · 31 Jan 2024Open

The linked statements(function _buy) do not affect the functionality of the codebase and appear to be either leftovers from older functionality.

Open the report
LowThird-Party Dependency UsageTangYuan-Audit · CertiK · 31 Jan 2024Open

The contract is serving as the underlying entity to interact with one or more third party protocols. The scope of the audit treats third party entities as black boxes and assumes their functional correctness. However, in the real world, third parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of third parties can possibly create severe impacts, such as increasing fees of third parties, migrating to new LP pools, etc. ```solidity=21 IRouter router; ``` - The contract `MktCap` interacts with third party contract with `IRouter` interface via `router`.

Open the report
LowUnchecked ERC-20 `transfer()`/`transferFrom()` CaTangYuan-Audit · CertiK · 31 Jan 2024Open

The return values of the `transfer()` and `transferFrom()` calls in the smart contract are not checked. Some ERC-20 tokens' transfer functions return no values, while others return a bool value, they should be handled with care. If a function returns `false` instead of reverting upon failure, an unchecked failed transfer could be mistakenly considered successful in the contract. ```solidity=120 IERC20(token1).transferFrom(address(_tokenDistributor),address(this), IERC20(token1).balanceOf(address(_tokenDistributor))); ``` --- ```solidity=134 IERC20(token0).transferFrom(address(_tokenDistributor),address(this), IERC20(token0).balanceOf(address(_tokenDistributor))); ``` --- ```solidity=180 if (toBurn > 0) IERC20(token0).transfer(address(0xdead), toBurn); ``` --- ```solidity=192 IERC20(token1).transfer(marketingAddress[i], cake); ``` --- ```solidity=133 else IERC20(token).transfer(dev,amount); ```

Open the report
LowZero Token Transfer can Cause Potential DoSTangYuan-Audit · CertiK · 31 Jan 2024Open

The function `setMarketing` does not check the parameter values non-zero. ```solidity function setMarketing( address[] calldata list, uint[] memory share ) public onlyOwner { require(list.length > 0, "DAO:Can't be Empty"); require(list.length == share.length, "DAO:number must be the same"); uint total = 0; for (uint i = 0; i < share.length; i++) { total = total.add(share[i]); } require(total > 0, "DAO:share must greater than zero"); marketingAddress = list; marketingShare = share; sharetotal = total; } ``` Hence in the trigger function, the cake to be transferred could be zero. However, transferring zero amount tokens in a loop can end up blocking the operation. ```soldity for (uint i = 0; i < marketingAddress.length; i++) { cake = amount2Marketing.mul(marketingShare[i]).div(sharetotal); IERC20(token1).transfer(marketingAddress[i], cake); } ``` This is a bit concerning as some ERC20 implementations revert on zero value transfers (see <https://github.com/d-xo/weird-erc20#revert-on-zero-value-transfers>). If at least one of the tokens includes this behavior, then the current implementation may cause a denial of service, as a zero amount transfer in this token will block the whole action and revert the transaction.

Open the report

Contracts1

AddressChainSource code
0x683e9dcf085e5efcc7925858aace94d4b8882024Chain: BNB ChainSource code: Verified source

Show this on your site

Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.

Content

Facts

Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="tangyuan"
></div>
</body>

Paste the code where the label should appear. It uses no API credit and updates by itself.

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us