Feyorra security record

BNB Chain, Ethereumfeyorra.comX

As of 30 Oct 2026, Feyorra has 1 audit report on Trustblock, by CertiK, dated 18 Feb 2025. That report lists no open critical findings.

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 Oct 2026. Trustblock does not review code.

Audits1

Newest first

AuditSecurity firmDateScopeCritical findingsReport
FEYSecurity firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com

Findings46

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

SeverityOpenAcknowledgedFixed
Critical000
High061
Medium018
Low10020
HighIncorrect Value Of Seconds In A DayFEY · CertiK · 18 Feb 2025Fixed

The constant `SECONDS_IN_DAY` is initialized to `30`, however, there are `86400` seconds in a day. This is used during interest calculations and staking calculations to determine the amount of interest and time that a user has staked. Since this value is set to 30, it will treat half a minute as a full day so that users will accumulate interest much faster than designed and will be able to close their stake with no penalty after only 2 minutes.

Open the report
Medium`cross_chain_transfer()` allows to withdraw lockeFEY · CertiK · 18 Feb 2025Fixed

Jetton-wallet `status & 1` bit set means the user can not send jettons. However, `cross_chain_transfer()` ignores the status and allows sending even from locked wallet.

Open the report
Medium`validateReceiver()` Does Not Ensure Only BridgeFEY · CertiK · 18 Feb 2025Fixed

The modifier `validateReceiver()` is used to validate the input `_receiverBridge`, which should be the corresponding `FeyorraBridge` deployed on the destination chain. However, the modifier only checks that this is not the zero address. If the input `_receiverBridge` does not correspond to a deployment of the `FeyorraBridge`, it will call `ccipReceive()` on the wrong address and will not provide any `FEY` tokens on the destination chain. Furthermore, if `transferFeyorraRequest()` is called for a custom chain, then the input `_receiverBridge` is only checked to have nonzero length. Similarly to above, this should be the corresponding `FeyorraBridge` deployed on the destination chain.

Open the report
MediumExtraArgs Is Hardcoded Causing Potential IncompatFEY · CertiK · 18 Feb 2025Fixed

According to Chainlink's best practices https://docs.chain.link/ccip/best-practices#using-extraargs, they suggest constructing `extraArgs` off chain in order to be compatible with future CCIP upgrades. However, instead of taking an input such as `bytes memory extraargs`, the code takes an input `_gasLimit` and constructs the `extraArgs` via the code: ```solidity extraArgs: Client._argsToBytes( Client.EVMExtraArgsV1({gasLimit: _gasLimit}) ) ``` As such the code may not be compatible with future CCIP upgrades. In particular, this does not allow supporting out of order execution.

Open the report
MediumLack of gas to process bounced `op::cross_chain_tFEY · CertiK · 18 Feb 2025Fixed

```c=99 () check_amount_is_enough_to_cross_chain_transfer(int msg_value) impure inline { int jetton_wallet_gas_consumption = get_precompiled_gas_consumption(); int send_cross_chain_transfer_gas_consumption = null?(jetton_wallet_gas_consumption) ? SEND_CROSS_CHAIN_TRANSFER_GAS_CONSUMPTION : jetton_wallet_gas_consumption; throw_unless(error::not_enough_gas, msg_value > get_forward_fee(MY_WORKCHAIN, CROSS_CHAIN_TRANSFER_NOTIFICATION_BITS, CROSS_CHAIN_TRANSFER_NOTIFICATION_CELLS) + get_compute_fee(MY_WORKCHAIN, send_cross_chain_transfer_gas_consumption) + get_compute_fee(MY_WORKCHAIN, RECEIVE_CROSS_CHAIN_TRANSFER_GAS_CONSUMPTION)); } ``` The code expects `msg_value` for `op::cross_chain_transfer` to be at least 2658000 + 6446000 + 8386000 = 17490000 = 0.01749 toncoins. However, in this case if the message `op::cross_chain_transfer_notification` will be bounced by jetton-minter due to lack of `ext_chain_fees`, the bounced message will not be processed by jetton-wallet and the original balance will be lost. The `total_supply` will be left intact.

Open the report
MediumManual Bridge Transfers Do Not Ensure Same RequesFEY · CertiK · 18 Feb 2025Fixed

Chainlinks CCIP router ensures that a request is not executed multiple times. However, the bridge has functionality to manually bridge which does not ensure the same request is not executed multiple times. While only the owner can call `manualExecuteBridgeTransfer()`, the owner may accidentally execute the same request multiple times resulting in a loss of funds for the protocol. Furthermore, if the CCIP router is given a setter function, then it is possible that the new router may not ensure that a request is not executed multiple times. As added protection the smart contract can also ensure the same request is not executed multiple times when bridging via CCIP as well. While this may cause redundant checks, it can reduce the trust assumptions on the CCIP router.

Open the report
MediumPotential race condition with `last_executed_mintFEY · CertiK · 18 Feb 2025Fixed

`op::mint` handler in jetton-minter works this way: 1. `admin_address` sends `op::mint` request with `query_id` equal to `last_executed_mint_query_id + 1` 2. `op::internal_transfer` message is sent to destination jetton wallet 3. `last_executed_mint_query_id` is incremented 4. In case the `op::internal_transfer` is bounced, the `last_executed_mint_query_id` is decremented back However, that opens the risk for race condition. The previous messages can be bounced when the new messages are already processed.

Open the report
MediumPotential Repeated `requestId` For Custom ChainsFEY · CertiK · 18 Feb 2025Fixed

The `requestId` for a custom chain is generated by calling `generateRandomBytes32()`, which is determined using the `nonce`, `msg.sender`, `block.timestamp`, and `address(this)`. If two bridge contracts on different chains are deployed to the same address, then it is possible for the same `requestId` to be generated on two different chains. This may cause issues in the bridging process.

Open the report
MediumSingle Point Of Failure With No Rate LimitsFEY · CertiK · 18 Feb 2025Fixed

The `FeyorraBridge` utilizes Chainlink's CCIP for the transfer of `data` in order to execute the bridging of their `FEY` tokens. However, it does not utilize the built in functionality to bridge tokens that follow the CCT standard. In particular, it does not include rate limits, so that if the bridge is compromised the amount of tokens that can be lost is the entire balance of the bridge. Similarly, if bridging to a custom chain that is not supported by Chainlink's CCIP, there are no limits on the amount of tokens that can be transfered, so that if the owner is compromised the amount of tokens that can be lost is the entire balance of the bridge.

Open the report
LowAllowlisted Sender Is Not Mapped With ChainFEY · CertiK · 18 Feb 2025Fixed

Allowlisted senders are not mapped with their corresponding source chain. This can cause issues if a sender is only intended to be allowlisted on certain chains and not on others.

Open the report
Show 10 more
LowCCIP Bridging Assumes All Source Chains Are EVM CFEY · CertiK · 18 Feb 2025Fixed

The internal `_ccipReceive()` function makes the following modifier call to verify the source chain and sender ```solidity onlyAllowlistedSource( _any2EvmMessage.sourceChainSelector, abi.decode(_any2EvmMessage.sender, (address)) ) ``` However, the sender is decoded as an EVM address. If the source chain is a non-EVM chain, then this will not give the correct sender address and can result in improper validation. Can you please clarify if the CCIP bridge is designed to only interact with EVM chains or if non-EVM chains are to be supported. If non-EVM chains are to be supported, then we recommend refactoring to properly handle non-EVM chains.

Open the report
LowCommented Out CodeFEY · CertiK · 18 Feb 2025Fixed

The cited lines contain commented code that can be removed from the codebase.

Open the report
LowContracts May Fail To Resume If Owner Renounce OwFEY · CertiK · 18 Feb 2025Fixed

The contract inherits from `Pausable` and `Ownable` at the same time. If the owner of a smart contract renounces ownership while the contract is paused, it means that there will be no one with the necessary permissions to unpause the contract. This could result in a permanent state of pause, effectively freezing all contract functionality that is dependent on the pause state. It's crucial to design smart contracts with secure ownership transfer mechanisms and emergency procedures to prevent such situations.

Open the report
LowContracts That Revert With Native Token TransfersFEY · CertiK · 18 Feb 2025Fixed

The function `excessIfNeeded()` is used to return any excess native tokens sent in the `msg.value` to the `msg.sender`. However, if the call to send the `refundAmount` fails, it will not revert and the `refundAmount` will be left in the contract. Note that the owner can call `withdrawNative()` to recover this amount, so it will not be locked in the contract.

Open the report
LowFragmented Liquidity Across Multiple ChainsFEY · CertiK · 18 Feb 2025Fixed

The `FeyorraBridge` contract requires users to transfer `FEY` when submitting a bridge request and transfers `FEY` from the contract when executing a bridge transfer. As this is the only bridge contract, it seems that all chains will have the `FeyorraBridge` lock/unlock tokens when bridging. As such the `FEYToken` will need to be deployed on each chain and the total amount that can be bridged must be transferred/minted to the bridge. However, the circulating supply of `FEY` is increasing due to the staking mechanism, so that the total supply of `FEY` may not be held by the bridge at a given time. This results in fragmented liquidity which increases operational overhead and complicates liquidity management.

Open the report
LowFunction Not PausableFEY · CertiK · 18 Feb 2025Fixed

In the `FeyorraBridge` contract, the `transferFeyorraRequest()` function is pausable. However, the `transferTokenOwnership()` function which can change the balances cannot be paused.

Open the report
LowInconsistent Use Of `_msgSender()` And `msg.sendeFEY · CertiK · 18 Feb 2025Fixed

Throughout the codebase `_msgSender()` from the contract `Context` is used. While this currently returns `msg.sender`, if in the future this is updated then it will cause an inconsistency for those that use msg.sender vs. `_msgSender()`.

Open the report
LowLack of external address validationFEY · CertiK · 18 Feb 2025Fixed

```c=199 int address_size = ext_address_slice.slice_bits(); throw_unless(error::invalid_external_address, (address_size >= 1) & (address_size <= MAX_EXETRNAL_ADDRESS_SIZE)); ``` `cross_chain_transfer()` in jetton-wallet validates that the external address is limited in size. However, it doesn't validate that there are no references. Adding extra data to `op::cross_chain_transfer` message and attaching minimal gas will make jetton-minter `total_supply` inconsistent. Jettons will be lost.

Open the report
LowMissing Emit EventsFEY · CertiK · 18 Feb 2025Fixed

The following functions update important contract states, however, they do not emit any event. - `updateCustomChain()` - `allowlistDestinationChain()` - `allowlistSourceChain()` - `allowlistSender()` - `withdrawToken()` - `withdrawNative()` - `deleteChain()` - `transferTokenOwnership()`

Open the report
LowMissing Error MessagesFEY · CertiK · 18 Feb 2025Fixed

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.

Open the report
Show 9 more
LowNo Getter Method For Pending OwnerFEY · CertiK · 18 Feb 2025Fixed

When transferring ownership a pending owner is set, who must then accept ownership to become the owner. While `s_owner` has a getter function, `s_pendingOwner` does not. This can make it difficult for a normal user to get transparent information and cause confusion.

Open the report
LowNo Method To Set Router AddressFEY · CertiK · 18 Feb 2025Fixed

While the CCIP router is not expected to change, it may change due to unforeseen circumstances relating to performance or issues with integrations on certain chains. There is no method to change the CCIP routers address in the event that this happens, in which case the protocol would need to be redeployed in order to change the routers address.

Open the report
LowPossible Loss Of the Data Due to Indexed DynamicFEY · CertiK · 18 Feb 2025Fixed

When attempting to index dynamic data types like `string`, `bytes`, `array`, or `struct` in Solidity, they don't get stored in their original form. Instead, the Ethereum log system stores the `Keccak-256` hash of these data types. While this approach ensures efficiency and cost-effectiveness, developers must be aware of it to correctly use and interpret logs, and they cannot retrieve the original string from its hash alone.

Open the report
LowReturn Variable UtilizationFEY · CertiK · 18 Feb 2025Fixed

The linked function declarations contain explicitly named `return` variables that are not used within the function's code block.

Open the report
LowRisks of `abi.encodePacked()`FEY · CertiK · 18 Feb 2025Fixed

The current implementation of `RequestIdGenerator.getRequestId()` employs `abi.encodePacked()` with multiple dynamic type inputs controlled by users: ```solidity bytes calldata _receiverBridge, bytes calldata _recipient ``` This encoding method introduces malleability, making it susceptible to manipulation as altered inputs could potentially achieve identical output bytes from `abi.encodePacked()`.

Open the report
LowSame Event Emitted By Both `transferFeyorraRequesFEY · CertiK · 18 Feb 2025Fixed

There are two functions `transferFeyorraRequest()`, one intended for non-custom chains which use Chainlink's CCIP, and the other for custom chains where there bridging will be done manually by the project. However, both emit the same event `TransferFeyorraRequest()`. This can cause issues if the bridge uses the emitted events to execute the bridge transfers on the destination chains. In particular, it must be ensured that for custom chains, the emitted events for non-custom chains will not be mistaken for custom bridging. This is of particular concern if a chains custom status is updated.

Open the report
LowTypos and outdated commentsFEY · CertiK · 18 Feb 2025Fixed

There are typos in the code: - "phaes" is supposed to be "phase" (stdlib.fc:L837) - "iternal" is supposed to be "internal" (gas.fc:L86) - "maunal" is supposed to be "manual" (gas.fc:L36) - "externbal" is supposed to be "external" (gas.fc:L60) - "EXETRNAL" is supposed to be "EXTERNAL" (jetton-utils.fc:L4) - "stdlib.fc#L733" is supposed to be "stdlib.fc#L746" (jetton-minter.fc and jetton-wallet.fc) - "burn_notification" comment at jetton-wallet.fc:L205 is outdated - "metadata url (contains snake slice without 0x0 prefix)" is supposed to be "metadata" - minimal fees comments in gas.fc:L14 are outdated - "ampped" is supposed to be "mapped" (Token.sol:L212) - "receipient" should be "recipient" (Token.sol:L16,L59) - "clsoed" should be "closed" (FEYToken.sol:L291) - "atleast" should be "at least" (FEYToken.sol:L319) - _sender comments in `Helper._transferCheck()` L50 is outdated - return comments in `Helper._transferCheck()` L54 is outdated

Open the report
LowUnnecessary InitializationFEY · CertiK · 18 Feb 2025Fixed

In `RandomBytes32Generator`, `nonce` is explicitly initialized to 0. However, it is a `uint256` which has a default value of 0.

Open the report
LowUnsafe Casting from uint256 to uint128FEY · CertiK · 18 Feb 2025Fixed

The linked code includes casting from `uint256` to `uint128`. While this is fine given the current parameter magnitudes, the subtle nature of this typecasting increases the risk that future changes to the implementation might overlook its impact. If the code is upgraded without properly accounting for this casting, larger variable sizes could result in unintended consequences, such as data truncation or precision loss, potentially introducing new issues.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

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="feyorra"
></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