As of 3 Nov 2026, MAP Protocol has 2 audit reports by 1 security firm on Trustblock; the latest is by CertiK, dated 5 Jan 2023. Those reports list 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 |
|---|---|---|---|---|---|
| Map Protocol | Security firm: CertiK | Date: | Scope: Files named in the report | 4 critical findings, fixed | Open · skynet.certik.com |
| Map Protocol - Near | Security firm: CertiK | Date: | Scope: Not recorded (see the report) | 1 critical finding, fixed | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 5 |
| High | 2 | 3 | 4 |
| Medium | 0 | 0 | 8 |
| Low | 5 | 0 | 90 |
In the contract `MCSToken` located in `mcs/near/mcs-token/src/lib.rs`, the accounts `controller` and `owner` have authority over the following functions: - `mint`: mint new tokens; - `burn`: burn tokens; - `set_metadata`: set fungible token metadata; - `set_owner`: set a new `owner`; - `set_controller`: set a new `controller`; - `upgrade_self`: upgrade contract code. --- In the contract `AdminControlled` located in `mcs/near/admin-controlled/src/macros.rs`, the account of contract itself has authority over the following functions: - set_paused(): Update mask with all paused events. --- In the contract `MapCrossChainService` located in `mcs/near/map-cross-chain-service/src/lib.rs`, the account pointed at the `owner` property has authority over the following functions: - `set_metadata`: Get the record information( validators, threshold and epoch) for the specified epoch. - `add_native_to_chain`: Add target chain for native token. - `remove_native_to_chain`: Remove target chain for native token. - `add_fungible_token_to_chain`: Allow the fungible token to be transferred to the target chain. - `remove_fungible_token_to_chain`: Remove the target chain id from the allow list of the fungible token. - `add_mcs_token_to_chain`: Allow the MCS token to be transferred to the target chain. - `remove_mcs_token_to_chain`: Remove the target chain id from the allow list of the MCS token. - `set_chain_type`: Set the type of a chain to bridge. - `set_owner`: Replace the current `owner`. - `set_map_light_client`: Set the account that works as on-chain light client. - `set_near_chain_id`: Set the chain ID for the Near end of the bridge. - `set_map_chain_id`: Set the chain ID for the Map Relay Chain end of the bridge. - `set_map_relay_address`: Set the address of the Map contracts on the Map Relay Chain. - `upgrade_self`: Upgrade the `MapCrossChainService` contract code. Any compromise to the privileged accounts may allow an hacker to take advantage of it and to, including but not limited to: - arbitrarily add or remove bridged token - mint token - pause pending transfers - replace the on-chain light client with a malicious one Besides, the deployer of the `MapCrossChainService` contract will have full access key over the `MapCrossChainService` contract and the `MCSToken` contracts deployed by calling the `deploy_mcs_token()` function. So the deployer has the ability to delete those two kinds of contracts and transfer the Near out of them to any other accounts.
Open the reportSmart contracts on the Near blockchain are deployed in accounts backed by regular key pairs. So, the overall security of a smart contract is related to the correct usage and custodial of such a key pair. On the Near side of Map Protocol both `MapLightClient` and `MapCrossChainService` fill a paramount role for the system correct behavior. `MapCrossChainService` locks funds that are transferred from Near to the other mapped blockchain and mints and burn token from external chain that are bridged to Near. `MapLightClient` provides the source of truth for the `MapCrossChainService` to verify facts and event happened on the Map Relay Chain. As a result, any compromise to the `MapCrossChainService` or `MapLightClient` contract's accounts may allow a hacker to take advantage of this authority and arbitrary mint that are supposed to not exist or unlock funds that should remain under the contract custodial.
Open the reportWhen transferring standard ERC20 deflationary tokens, the input amount may not be equal to the received amount due to the charged transaction fee. As a result, an inconsistency in the amount will occur and the transaction may fail due to the validation checks. For example, if a user sends 100 deflationary tokens (with a 10% transaction fee) to the target contract, only 90 tokens actually arrived in the contract.
Open the report**mcs/evm/contracts/MAPCrossChainServiceRelay.sol** ```solidity function _transferInOtherChain(transferOutEvent memory outEvent, uint256 outAmount, bytes memory toChainToken) internal checkOrder(outEvent.order_id) nonReentrant whenNotPaused { //... uint256 outMap = getToChainAmount(mapToken, outEvent.to_chain, selfChainId, outAmount); uint256 feeMap = getChainFee(outEvent.to_chain, mapTokenAddress, outMap); uint256 fee = getToChainAmount(mapToken, selfChainId, outEvent.to_chain, feeMap); outAmount = outAmount.sub(fee); if (checkAuthToken(mapTokenAddress)) { IMAPToken(mapTokenAddress).mint(address(this), outMap); IMAPToken(mapTokenAddress).burn(outMap.sub(feeMap)); } //... } ``` In the function `_transferInOtherChain()`, if `mapTokenAddress` is an `AuthToken`, the function `mint()` of `IMAPToken` will be called first to increase the balance of the contract, followed by the function `burn()` to decrease the balance of the contract. If it only mints the difference in the number of tokens to the contract, the `burn()` function could be removed.
Open the reportThere is the risk that problems will arise because of RLP encoding compatibility issues. Recursive Length Prefix (RLP) serialization is used extensively in Ethereum's execution clients. RLP standardizes the transfer of data between nodes in a space-efficient format. The purpose of RLP is to encode arbitrarily nested arrays of binary data. RLP is the primary encoding method used to serialize objects in Ethereum's execution layer. The main purpose of RLP is to encode structures. The current RLP encoder and decoder are not in compliance with Ethereum RLP guidelines (https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp#definition) and implementations.
Open the reportThe cross-chain program `Messenger` listens for events emitted on the source chain and builds a proof for the respective event. Then it transmits the message of the event and receipt proof to the destination chain. However assume the following: 1. Alice on Ethereum transfers token A to herself on Near where there is not enough token A. 2. The `Messenger` submits the receipt proof by calling the `transfer_in()` function defined on Near. 3. Within the `transfer_in()` function, a failure appears. 4. The error message is reported by calling the `report_transfer_in_fail()` function. The `Messenger` would catch that error message. However Alice's tokens are locked on Ethereum.
Open the reportThe implementation of `MCSToken` contract wraps the `FungibleToken` struct from the `near_contract_standards` library. `FungibleToken` implements the `near_contract_standards::StorageManagement` that let any user to fund an `account_id` paying its staking storage deposit. If `account_id` already exists the deposited amount is refunded to the `env::predecessor_account_id()` that invoked `storage_deposit`. When an amount of `MCSToken` needs to be minted because of a transfer incoming into the Near side of the bridge, the `MapCrossChainService` contract issues a `Promise` to call the `MCSToken::mint` function, attaching a deposit for the staking storage, whose amount is configured in `MapCrossChainService::mcs_storage_transfer_in_required`. Problem resides in the fact that if the account that should benefit the minted amount already exists on the `MCSToken` instance, the refund is payed to the `env::predecessor_account_id()`, so to the `MapCrossChainService` contract. However, no functionality is provided to let the `transfer_in` caller redeem the unused deposit. Since *Messengers* are in charge of notifying cross-chain assets movements, this issue can unwillingly drain their resources moving NEAR token from them to the `MapCrossChainService` contract. In a practical example:\ let's assume that Alice wants to transfer to Bob an amount of "TokenA" from the Map Relay Chain to the Near blockchain and that "TokenA" is mapped on Near as an `MCSToken`. Bob already owns some "TokenA" so he is already registered in the `MCSToken` contract.\ Alice locks `MCS` tokens on the Map Relay Chain. One of the available *Messengers* will relay the event to the `MapCrossChainService` contract on the Near side, calling the `transfer_in` function. Within the `process_transfer_in()` function, an amount of `MCS` tokens will be minted to Bob by calling the `mint()` function of `MCSToken` contract along with the attached deposit `self.mcs_storage_transfer_in_required` which is paid by the *Messenger*. Such a deposit will be refunded to the `MapCrossChainService` contract because Bob is already registered. However, the refunded deposit for `Messenger` does not include the refunded storage deposit from the `MCSToken` contract. In fact, `self.mcs_storage_transfer_in_required` is already subtracted from `ret_deposit` before the `finish_transfer_in()` function is called. Eventually, *Messengers* will see their funds moved to the `MapCrossChainService` contract without a real justification.
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="map-protocol"></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