PAWSWAP

CertiKCode version: not recorded (see the report)

CertiK reviewed PAW Chain (PAWSWAP) on 23 Aug 2023: 24 findings, 0 critical; 18 marked fixed, 6 open.

No open critical findings
Open PAW Chain’s security record

The original report was removed from its address (seen 20 Oct 2026).

Trustblock does not review code.

Findings24

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

SeverityOpenAcknowledgedFixed
Critical000
High201
Medium003
Low4014
HighPotential Flashloan AttackFixed

Flash loans are a way to borrow large amounts of money for a certain fee. The requirement is that the loans need to be returned within the same transaction in a block. If not, the transaction will be reverted. An attacker can use the borrowed money as the initial funds for an exploit to enlarge the profit or manipulate the token price in decentralized exchanges. The function `CalculatePAWequivalent()` relies on price calculations that are based on-chain, meaning they are susceptible to flash-loan attacks by manipulating the price of given pairs to the attacker's benefit. The balance of the `PAW` in the pair contract can be manipulated as described in the scenario. ```solidity function CalculatePAWequivalent(uint256 amount) public view returns(uint256){ return (((ERC20(PAW).balanceOf(PairContract)*((((1000000000000000000 * amount) / (ERC20(PairContract).totalSupply())))) / 1000000000000000000))*2); } ```

Medium`ChangeMultiplier()` Does Not Settle Rewards WithFixed

The function `ChangeMultiplier()` in the linked contracts does not settle the current rewards with the old rate. All the staking users will be forced to use the new reward rate. This may be unfair to the user if the new rate is lower.

MediumIncorrect Claim ConditionsFixed

The conditions to trigger the function `Claim()` are different in the functions `Deposit()` and `Withdraw()`. The `if` condition in the function `Deposit()` lacks the check of `ERC20(wPAW).balanceOf(address(this)) >= (GetUnclaimed(msg.sender))`. As a result, if the balance of the token `wPAW` is not sufficient, the users may not be able to call the function `Deposit()`. ```solidity //Deposit if(Deposits[msg.sender] > 0 && RewardsPaused == false){ Claim(); } //Withdraw if((ERC20(wPAW).balanceOf(address(this)) >= (GetUnclaimed(msg.sender))) && RewardsPaused == false){ Claim(); } ```

MediumLogic Issue On `stakedTokenSupply`Fixed

In the linked contracts in the new commit [cd93a72a77aed596685d4f948976196318a9cdbb](https://github.com/Pawkishi/PAWSWAPtoken/tree/cd93a72a77aed596685d4f948976196318a9cdbb), the value of `stakedTokenSupply` will be the current contract's balance of the staking token(`PAWToken` or `lpToken`). However, this does not consider direct token transfers. If someone mistakenly transfers the staking token directly to the current contract, the result of the variable `stakedTokenSupply` will be incorrect and include the direct transfer amount. This will cause all the stakers to lose some of their rewards.

LowChecks Effects Interaction Pattern Not UsedFixed

In functions `Deposit()` and `Withdraw()` of the linked contracts `PAWFlexibleStaking` and `PawLPStaking`, the Checks Effects Interaction Pattern is not strictly followed.

LowIncompatibility with Deflationary TokensFixed

When transferring deflationary ERC20 tokens, the input amount may not be equal to the received amount due to the charged transaction fee. For example, if a user sends 100 deflationary tokens (with a 10% transaction fee), only 90 tokens actually arrived to the contract. However, a failure to discount such fees may allow the same user to withdraw 100 tokens from the contract, which causes the contract to lose 10 tokens in such a transaction. Reference: https://thoreum-finance.medium.com/what-exploit-happened-today-for-gocerberus-and-garuda-also-for-lokum-ybear-piggy-caramelswap-3943ee23a39f For example: ```solidity=50 ERC20(PairContract).transferFrom(msg.sender, address(this), amount); ``` - Transferring tokens by `amount`. ```solidity=52 Deposits[msg.sender] = (Deposits[msg.sender] + amount); ``` - The `amount` appears to be used for bookkeeping purposes without compensating the potential transfer fees.

LowLogic Issue On `holderUnlockTime`Fixed

In the contract `PAWLockedStaking`, the user needs to stake for at least a `lockDuration` before withdraw. 1. The variable `holderUnlockTime[msg.sender]` is used to record the unlock time of each user instead of a single deposit. The below code snippet in the `deposit()` function will not update the `holderUnlockTime[msg.sender]` if there are already locked deposit from the given user. Therefore, the user can shorten the lock time of multiple deposit. ```solidity if(holderUnlockTime[msg.sender] == 0){ holderUnlockTime[msg.sender] = block.timestamp + lockDuration; } ``` 2. The conditions of withdrawal restriction and emergency penalty are slightly different. If the block.timestamp equals holderUnlockTime[msg.sender], the user can successfully withdraw the tokens with rewards but still need to pay the exit penalty using `emergencyWithdraw()`. ```solidity require(holderUnlockTime[msg.sender] <= block.timestamp, "May not do normal withdraw early"); if(holderUnlockTime[msg.sender] >= block.timestamp) ```

LowLogic Issue On Function `rewardsRemaining()`Fixed

The function `rewardsRemaining()` calculate the remaining rewards as `rewardToken.balanceOf(address(this)) - totalStaked`. Based on our understanding, the remaining rewards is the current reward balance - current rewards to be distributed, which should be `rewardToken.balanceOf(address(this)) - calculateNewRewards`.

LowMathematical IssueFixed

Performing integer division before multiplication truncates the low bits, losing the precision of the calculation. Although the `1000000000000000000` seems to be a multiplying to mitigate the issue, the `*2` operation is placed at the end. Also, the statement contains many redundant parentheses making the code hard to read. ```solidity=155 return (((ERC20(PAW).balanceOf(PairContract)*((((1000000000000000000 * amount) / (ERC20(PairContract).totalSupply())))) / 1000000000000000000))*2); ```

LowMissing Emit EventsFixed

There should always be events emitted in the sensitive functions that are controlled by centralization roles.

Show 8 more
LowMissing Error MessagesFixed

The **require** can be used to check for conditions and throw an exception if the condition is not met. It is better to provide a string message containing details about the error that will be passed back to the caller.

LowMissing Zero Address ValidationFixed

Addresses should be checked before assignment or external call to make sure they are not zero addresses. For example: ```solidity=101 PairContract = NewPair; ``` - `NewPair` is not zero-checked before being used. --- ```solidity=133 Operator = NewOperator; ``` - `NewOperator` is not zero-checked before being used.

LowNo Reward If Withdraw During Reward PauseFixed

If the reward is paused by calling the function `PauseRewards()`, the user can not get any rewards when calling the functions `Deposit()`, `Withdraw()`, `Claim()`. However, in the `Deposit()`, the user's `LastUpdateUnix[user]` is updated; in the function `Withdraw()`, the user's `Deposits[msg.sender]` amount is updated. As a result, even if the user has staked before the pause time, he/she can not get the rewards any more. Based on our understanding, it is reasonable that there is no reward during the pause time, but the user should get the rewards for the staking period before the pause time.

LowRedundant StatementsFixed

The linked statements do not affect the functionality of the codebase and appear to be either remnants of test code or older functionality. - function _setDividendBalance(), the user's stake is already recorded in `user.amount`, not necessary to mint/burn shares to the user as well. - function estimateAPY(), which is deprecated in the version [76547e0445bacfc912f928ce7c3eac9cb4f4e4cc.](https://github.com/Pawkishi/PAWSWAPtoken/commit/76547e0445bacfc912f928ce7c3eac9cb4f4e4cc)

LowReward Calculations LogicFixed

The reward calculation logic in the linked stake contracts is not very clear. The reward is calculated with the below code snippet. What is the meaning of the `/ 1000000000000000` operation? ```solidity Unclaimed = (((RewardMultiplier * Time) * Deposits[user]) / 1000000000000000); Unclaimed = (((RewardMultiplier * Time) * CalculatePAWequivalent(Deposits[user])) / 1000000000000000); ```

LowUnchecked ERC-20 `transfer()`/`transferFrom()` CaFixed

The linked contracts use the transfer()/transferFrom() call without checking their return values. For example: ```solidity ERC20(PairContract).transferFrom(msg.sender, address(this), amount); ERC20(PairContract).transfer(msg.sender, amount); ERC20(wPAW).transfer(msg.sender, Unclaimed); ERC20(PAW).transfer(msg.sender, ERC20(PAW).balanceOf(address(this))); ```

LowUnnecessary ArrayFixed

The contract only maintains one `PoolInfo` struct, so the array `PoolInfo[]` is unnecessary.

LowUpdate Pool in Function `addRewardTreasure()` andFixed

In the linked contracts in the new commit [cd93a72a77aed596685d4f948976196318a9cdbb](https://github.com/Pawkishi/PAWSWAPtoken/tree/cd93a72a77aed596685d4f948976196318a9cdbb), the contract owner will use the function `addRewardTreasure()` to transfer reward tokens to the current contract. Also, the function `emergencyWithdraw()` will add back the deducted `rewardTreasure`. However, the functions `addRewardTreasure()` and `emergencyWithdraw()` do not call the function `_updatePool()` to allocate the reward immediately. As a result, the reward will be allocated at the next call to the function `_updatePool()` with `deposit()`, `withdraw()`, `claim()`, etc. This will cause the users to lose some of the rewards.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Part of PAW Chain’s security record

PAW Chain
Audits1 audit by 1 firmLast audit Aug 2023, by CertiK.
Critical findingsNo open critical findingsIn 1 report.
Open PAW Chain’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

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