As of 3 Nov 2026, Pension has 1 audit report on Trustblock, by CertiK, dated 20 Oct 2022. That report lists no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Pension Token | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 3 | 0 | 0 |
| Medium | 1 | 0 | 0 |
| Low | 14 | 0 | 0 |
In the contract `Ownable` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - transfer ownership through `transferOwnership()` - permanently renounce ownership through `renounceOwnership()`  In the contract `PensionProtocolToken` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - set `liquidityAddress`, `marketingAddress` and `developmentAddress` through `setFeeReceivers()` - set the fees up to fifteen in total through `setFees()` - exempt or include an address from/in fees through `setFeeExempt()` - transfer tokens on this contract to any address through `rescueToken()` - transfer ether on this contract to any address through `clearStruckBalance()` - set the next timestamp for rebasing through `setNextRebase()` - add or remove automated market maker pair through `setAutomatedMarketMakerPair()` - set the rebasing time delay up to eighteen hundred seconds through `setRebaseFrequency()` - set the reward rate and denominator through `setRewardYield()`  In the contract `PensionProtocolToken` the role `_owner` has authority over the functions shown below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - add liquidity through `swapBack()` - mint uncapped "gon" tokens on any account through `mint()` - burn from any account through `burn()` - rebase the supply of the token through `manualRebase()` In the contract `TokenHandler` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - take all tokens on this contract through `sendTokenToOwner()`  In the contract `WhitelistedRole` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - add an account to the whitelist through `addWhitelisted()` - remove an account from the whitelist through `removeWhitelisted()` 
Open the reportIn the contract `Ownable` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - transfer ownership through `transferOwnership()` - permanently renounce ownership through `renounceOwnership()`  In the contract `PensionBank` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - set the pension token address through `setPensionToken()` - update the pension tax up to eighty percent through `updatePensionTax()`  In the contract `PensionBank` the role `_whitelisted` has authority over the functions shown below. Any compromise to the `_whitelisted` account may allow the hacker to take advantage of this authority and - rebase the pension token and take dividends through `rebase()` In the contract `WhitelistedRole` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and - add an account to the whitelist through `addWhitelisted()` - remove an account from the whitelist through `removeWhitelisted()` 
Open the reportTokens are sent to the deployer when deploying the contract. This could be a centralization risk as the deployer can distribute tokens without obtaining the consensus of the community.
Open the reportBalance is not added to `liquidityBalance` which will always be zero.
Open the reportThe calculated `supplyDelta` would always be non-negative given that `rewardYield` and `circulatingSupply` are non-negative. Yet the rebasing logic assume that it could be negative.
Open the reportThe mentioned functions are declared as `public`, contain array function arguments, and are not invoked in any of the contracts contained within the project's scope. The functions that are never called internally within the contract should have external visibility.
Open the reportThe function that affects the status of sensitive variables should be able to emit events as notifications to users.
Open the reportThe given input is missing the check for the non-zero address.
Open the reportThe aforementioned code is not used and seems redundant.
Open the reportThe `_transferFrom` method restricts token transfer to only `excludedAccount`. While listed `automatedMarketMakerPairs` are allowed to send but not allowed to receive pension tokens, this means the user cannot freely sell or transfer their pension tokens. To sell they would have to call `sell()` in the `PensionBank` contract, yet it would incur a high 50% of pension tax.
Open the reportThe contract is serving as the underlying entity to interact with third-party protocols. The scope of the audit treats 3rd party entities as black boxes and assumes their functional correctness.
Open the reportThe return value of the transfer()/transferFrom() call is not checked. ```solidity=202 IERC20(token).transfer(owner(), IERC20(token).balanceOf(address(this))); ``` --- ```solidity=445 IERC20(BUSD).transfer(marketingAddress, busdForMarketing); ``` --- ```solidity=449 IERC20(BUSD).transfer(developmentAddress, busdForDevelopment); ``` --- ```solidity=453 IERC20(BUSD).transfer(teamAddress, busdForTeam); ``` --- ```solidity=561 try IERC20(address(pensionToken)).transferFrom(msg.sender, address(this), userPensionBalance) {} catch {revert("transfer from caller failed");} ``` --- ```solidity=565 IERC20(BUSD).transfer(msg.sender, busdBalance * (100-pensionTax) / 100); ```
Open the report`excludedFromDividends` is not being initialized in the constructor and cannot be written by any methods.
Open the reportThe linked statement make an assignment of a global variable.
Open the reportThe functions `get()`, `getIndexOfKey()`, `getKeyAtIndex()` and `size()` are declared but never used in the contract.
Open the reportThe return value of an external call is not stored in a local or state variable. ```solidity=479 IERC20(BUSD).approve(address(router), busdAmount); ``` --- ```solidity=482 router.addLiquidity(address(this), address(BUSD), tokenAmount, busdAmount, 0, 0, address(liquidityAddress), block.timestamp); ``` --- ```solidity=337 BUSD.approve(address(dexRouter), busdBalance); ``` --- ```solidity=340 dexRouter.swapExactTokensForETH( busdBalance, 0, // accept any amount of Ethereum path, address(this), block.timestamp ); ``` --- ```solidity=578 IERC20(address(pensionToken)).approve(address(dexRouter), tokenAmount); ``` --- ```solidity=594 IERC20(BUSD).approve(address(dexRouter), amountInBusd); ```
Open the reportCalling `manualRebase()` in the token contract deflates the token somewhat and the user's balance is increased proportionally while calling `rebase()` in the bank contract additionally mint extra token and then sell them for dividends. Generally, the bank user should receive as many dividends as token holders' balance increases but this may not be the case if `manualRebase` is called by external other than the bank.
Open the reportThe linked variables could be declared as `constant` since these state variables are never modified.
Open the reportThe reports name a repository or files. Open a report to see its scope.
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.
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.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="pension"></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