Gala security record

As of 3 Nov 2026, Gala has 4 audit reports by 1 security firm on Trustblock; the latest is by CertiK, dated 22 Nov 2024. Those reports list no open critical findings. It also holds 1 deployed contract on 1 chain and 1 incident (latest 19 May 2024).

Critical findings
No open critical findings
Across the 4 reports, 2 critical findings were reported. Each is marked fixed by the firm that reported it. See the findings
Incident
Incident 19 May 2024
Source: De.Fi incident database. 2 audits have been published since. See the incident
Open the latest report
Your label, live
Get the label for your site

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

Audits4

Newest first

AuditSecurity firmDateScopeCritical findingsReport
Gala Games - TON BridgeSecurity firm: CertiKDate: Scope: Not recorded (see the report)1 critical finding, fixedOpen · skynet.certik.com
Gala - FilmSecurity firm: CertiKDate: Scope: 1 address on EthereumNo open critical findingsOpen · skynet.certik.com
Gala - governance voting APISecurity firm: CertiKDate: Scope: Not recorded (see the report)1 critical finding, fixedOpen · skynet.certik.com
Gala Games - GalaV2Security firm: CertiKDate: Scope: Files named in the reportNo open critical findingsOpen · skynet.certik.com

Findings37

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

SeverityOpenAcknowledgedFixed
Critical002
High212
Medium003
Low5022
CriticalSignature can be fakedGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

```c=20 (int, int, int, int) ecrecover (int hash, int v, int r, int s) asm "ECRECOVER"; ... (int h, int x1, int x2, int success) = ecrecover(packet_hash, v, r, s); slice rec_pubkey = begin_cell().store_uint(h, 8).store_uint(x1, 256).store_uint(x2, 256).end_cell().begin_parse(); throw_unless(error::signature, rec_pubkey.equal_slice_bits(pubkey)); ``` `ECRECOVER` opcode [returns](https://docs.ton.org/learn/tvm-instructions/tvm-upgrade-2023-07#secp256k1) either 0 or `h x1 x2 -1`. In case 0 is returned, only **one value is pushed on stack**. Extracting 4 values will populate `(int h, int x1, int x2, int success)` with the values that were already on top of stack. These values are `r, s, v, success` completely controlled by the caller. The `success` output is **not checked** by the function. As a result, the caller can craft the signature (520 bits) that will satisfy the condition `rec_pubkey.equal_slice_bits(pubkey)` and pass the check. All funds can be stolen.

Open the report
CriticalThe "poll/cast" API allows voting with a negativeGala - governance voting API · CertiK · 9 Aug 2023Fixed

The "poll/cast" endpoint allows users to vote with their voting power. The number of votes the user wants to submit is referred to as the "multiplier" in the request body. Two issues are found regarding the API that, if used together, can allow the voter to have infinite voting power. * Issue 1: When a user supplies a negative "multiplier" in the API call, it will cause the "userVotesUsed" to become a negative number and effectively increase the user's total voting power. * Issue 2: Casting a vote to a non-existing option is allowed. For example, if there are only 3 options to vote on, the user can vote on option 100.

Open the report
HighPacket signatures checking is flawedGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

In `bridge_gateway` `op::route_unlock` handler the signature check is handled incorrectly: 1. It cycles `until(signatures.slice_refs_empty?())` but never updates the `signatures` with the next ref. Same signature will be used over and over again. 2. It doesn't validate the number of signatures provided. No threshold is set, one signature is always enough. 3. It doesn't ensure that the signatures are from different verifiers. Same signature can be repeated several times.

Open the report
HighUsers can vote on a completed pollGala - governance voting API · CertiK · 9 Aug 2023Fixed

The "poll/cast" endpoint allows users to vote with their voting power. It was found that users can vote on a completed poll and modify the result.

Open the report
MediumLack of replay protectionGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

The signed messages don't follow the [EIP-712 recommendations](https://eips.ethereum.org/EIPS/eip-712#specification). The domain separator doesn't include: 1. `name` - the user readable name of signing domain, i.e. the name of the DApp or the protocol. 2. `verifyingContract` - the address of the contract that will verify the signature. 3. `encodeType` - like "op::route_unlock(args)"h As a result, the message signed by verifiers for gateway in one chain (i.e. testnet) can be replayed on another one, or on another gateway deployment. Or the message signed with another purpose can be submitted to `op::route_unlock` handler.

Open the report
MediumWrong gas management in `op::route_unlock`Gala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

`bridge_gateway` `op::route_unlock` handler doesn't check that the gas provided is enough to finish the workflow. Lack of gas can lead to incomplete transaction execution.

Open the report
MediumZero Address Can be `blocklisted`Gala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

The `BLOCKLISTER_ROLE` can `blocklist()` the zero address. This would prevent all mints and burns and it may not be immediately clear what is causing the issue.

Open the report
Low`end_parse()` Is MissingGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

The data is packed in slice and parsed by the contract. To ensure the slice has the expected data structure and no data left after parsing, `end_parse()` can be applied to the slice. If slice is empty, it throws an exception.

Open the report
Low`jetton_bridge` doesn't allow fees collectingGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

`jetton_bridge` doesn't allow the owner to collect fees. `ton_coin_bridge` doesn't allow the owner to change the flat fee.

Open the report
Low`load_grams()` is deprecatedGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

`load_grams()` is deprecated. `load_coins()` should be used instead.

Open the report
Show 10 more
Low`wallet_address` is used as `response_destinationGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

`response_destination` in `op::transfer` message is used to accept gas excesses. Using `wallet_address` is unreasonable since it is not expected to collect extra gas.

Open the report
LowCorrect workchain not enforcedGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

```c=2 (_, int wallet_hash) = parse_std_addr(wallet); ``` It is not ensured the address workchain is basechain. Unexpected messages from the masterchain can break the contract invariants.

Open the report
LowInconsistent payload serializingGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

`decode_payload()` reads `extra = payload~load_maybe_ref()`. `load_maybe_ref()` loads 1 bit and if it is true, loads first ref and returns it with slice remainder. However, `encode_payload()` doesn't store that 1 bit. Trying to `decode_payload()` that was encoded by `encode_payload()` will result in cell underflow.

Open the report
LowLack of sanity checksGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

```c=89 amount -= flat_fee; ``` It is not checked that `amount` is bigger than `flat_fee`. As a result, the transaction will fail with integer underflow during `store_coins()`.

Open the report
LowOutdated commentsGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

Some comments are outdated. - `lock_ton#1bc9f191` is in fact `0x6372e897` - `unlock#1d1c0c53 amount:Grams instance:uint(256) recipient:^RecipientBody wallet_hash:uint(256) = InternalMsgBody;` `unlock` tag is in fact 5. The message payload is stored in the separate cell. `Grams` should be `Coins`. - etc.

Open the report
LowSusceptible to Signature MalleabilityGala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

The signature malleability is possible within the Elliptic Curve cryptographic system. An Elliptic Curve is symmetric on the X-axis, meaning two points can exist with the same `X` value. In the `r`, `s` and `v` representation this permits us to carefully adjust `s` to produce a second valid signature for the same `r`, thus breaking the assumption that a signature cannot be replayed in what is known as a replay-attack. Appendix F in the [Ethereum Yellow paper](https://ethereum.github.io/yellowpaper/paper.pdf) defines the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. ```c=144 if(v >= 31) { v = v - 31; } ``` The current code allows bigger `v` and doesn't check `s`.

Open the report
LowUnsafe handle of `op::transfer_notification`Gala Games - TON Bridge · CertiK · 22 Nov 2024Fixed

`jetton_bridge::op::transfer_notification` handler works this way: 1. unpacks `op::transfer_notification` message 2. ensures `msg_value >= flat_fee` 3. unpacks the payload of `op::transfer_notification` message 4. sends `op::log_request` to the gateway However, if the `msg_value` is not enough or payload is in a wrong format, the tokens will not be returned to the owner.

Open the report
Low`_totalMinted` vs. `_totalSupply`Gala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

### `Gala` Token - Version 1 In version 1 of the `Gala` token, the `_totalMinted` value is only updated during calls to `mint()`, where it is updated as: ```solidity _totalMinted = _totalMinted.add(amount); ``` In the hook `_beforeTokenTransfer()`, the update to this value is checked against the set `_cap` when minting: ```solidity require(totalMinted().add(amount) <= cap(), "ERC20Capped: cap exceeded"); ``` Since `_totalMinted` is only updated in `mint()` and is checked against the `_cap` value, this means that only 50 billion `GALA` will ever be minted, and that as users burn the token, the `_totalSupply` will monotonically decrease towards 0. --- ### `GalaV2` While `_totalMinted` is still updated and checked during functions `mint()` and `mintBulk()` in the same way for `GalaV2`, the value `_totalMinted` is now updated in functions `burn()` and `burnFrom()` as follows: ```solidity _totalMinted = _totalMinted - amount; ``` This means that as tokens are burned, an equivalent amount becomes available again to be minted. As such, this new update to `_totalMinted` makes the value consistent with `_totalSupply` throughout the lifetime of the `GalaV2` token. Indeed, the `_cap` on `_totalMinted` is also a `_cap` on the `_totalSupply`, making the values equivalent in all respects, within the current contract's set up.

Open the report
LowCostly Operation Inside LoopGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

Accessing storage variables in a loop can be costly in terms of gas consumption. ```solidity=86 _totalMinted = _totalMinted + amounts[i]; ```

Open the report
LowDiscussion on `MINTER_ROLE`Gala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

There is custom functionality created for accomplishing granting or revoking the `MINTER_ROLE`: `addMinter()` and `removeMinter()`. Moreover, the functions `mint()` and `mintBulk()` also perform specific checks to ensure that the `MINTER_ROLE` is also not blocklisted. Please provide more information on the types of accounts you plan to grant the `MINTER_ROLE`. Is it within the design plans of the project to allow for multiple accounts to take this role; will general users be given this privilege, where there may be a need to blocklist bad actors?

Open the report
Show 9 more
LowInconsistency Between `mint()` and `mintBulk()`Gala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

Function `mint()` allows for a zero input `amount`, while each `amounts[i]` must be positive in `mintBulk()`

Open the report
LowInconsistent Use of `msg.sender` and `_msgSender(Gala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

The child contract uses both `msg.sender` and `_msgSender()` in its functions, while the inherited contracts consistently use `_msgSender()`. If `_msgSender()` is ever updated to be anything other than `msg.sender`, this may cause inconsistencies.

Open the report
LowInheritance `PausableUpgradeable` is not InitialiGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

Inherited contract `PausableUpgradeable` is not initialized through call to `__Pausable_init()` in the `initialize()` function.

Open the report
LowMinters can be added and removed when contract isGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

Functions `addMinter()` and `removeMinter()`, which grant the `MINTER_ROLE`, can only be called when the contract is not `_paused`; however, `grantRole()` and `revokeRole()` may still be called for any address and role, even when the contract is `_paused`.

Open the report
LowMissing Zero Address ValidationGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

The cited address input is missing a check that it is not `address(0)`.

Open the report
LowRedundant `notBlocklisted` and `whenNotPaused` ChGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

The checks using the `notBlocklisted` and `whenNotPaused` modifiers are redundant in the following functions, since the function calls interact with hook `_beforeTokenTransfer()`, covering all possible cases: - `mint()`; - `mintBulk()`; - `burn()`; - `burnFrom()`

Open the report
LowRedundant Checks on Admin RolesGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

Functions `addMinter()`, `addUpgrader()`, `addBlocklister()`, and `transferAdmin()` all have redundant checks to modifier `onlyRole`. The aforementioned functions specify that only the `DEFAULT_ADMIN_ROLE` may call these functions; by default, this is the `adminRole` assigned to all roles. The redundancy also exists within functions `removeMinter()`, `removeUpgrader()`, and `removeBlocklister()`. In the case where `DEFAULT_ADMIN_ROLE` account calls a function like `addMinter()`, the check on the `_msgSender()` confirming they are the `DEFAULT_ADMIN_ROLE` is performed twice; once at the beginning of `addMinter()` and once at the execution of `grantRole()`. --- It is noted that if the contract is ever upgraded, each `role` may be assigned an `adminRole` distinct from `DEFAULT_ADMIN_ROLE`. This can be done through adding additional functionality which interacts with internal function `_setRoleAdmin()`. For example, it is possible that another "MinterAdmin" is assigned separate from the `DEFAULT_ADMIN_ROLE` as the `adminRole` for `MINTER_ROLE`. In such a case, this "MinterAdmin" would be able to call `grantRole()` and `revokeRole()` directly, but would not be able to call function `addMinter()`, since this function specifies that only `DEFAULT_ADMIN_ROLE` may perform the call. Furthermore, `DEFAULT_ADMIN_ROLE` would cease to be able to call `addMinter()` in this instance.

Open the report
LowThe keyword `super` is unnecessaryGala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

The use of the `super` keyword is not necessary since there is no override and there is a well-defined path to the internal `_pause()` and `_unpause()` functions inherited from `ERC20PausableUpgradeable`, and to the public `hasRole()` function `from `AccessControlUpgradeable`.

Open the report
LowVariable Can Be Declared As `constant`Gala Games - GalaV2 · CertiK · 20 Apr 2023Fixed

The variable `_cap` assigned in the initializer is never modified throughout the contract and is a hardcoded value. Instead, the variable can be initialized before the function call, with keyword `constant`, to optimize gas usage.

Open the report

Incidents1

Attached through a shared contract address. Our incident data ends in Oct 2026.

Incident

Incident,

Source: De.Fi incident database.

Audits before it
2.
Audits since
2, the latest dated 22 Nov 2024.

Contracts1

AddressChainSource code
0xacc36ebdc4b394f0b03ee2bbd1a6b701c0ab15cdChain: EthereumSource code: Verified source

All 1 address and the 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="gala-games"
></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