Revolutionize Your Business with Xamer's Smart Audit Services
On-chain smart contract security monitoring
Starfish Finance aims to be a multichain DeFi x NFT-Fi protocol in the Polkadot ecosystem with multi-token stable and weighted swap (based on Balancer v2), cross-chain aggregation for crypto and NFTs, and unlock the opportunity for liquidity in NFTs.
Audits
Onboarded Date
12/Dec/2022
Contracts
0xa71...9de24
Website
We talked about a project on linkedin.
Create new project Buildng product
Adding a new event with attachments
added a new member to velzon dashboard
These customers can rest assured their order has been placed.
They all have something to say beyond the words on the page. They can come across as casual or neutral, exotic or graphic.
2 days left notification to submit the monthly sales report. Reports Builder
User Erica245 submitted a ticket.
Team Leader & HR
Projects
Tasks
Full Stack Developer
Project Manager
UI/UX Designer
Team Leader & Web Developer
Backend Developer
Front-End Developer
Web Designer
Wed Developer
Showing 1 to 10 of 12 entries
All Findings
Acknowledge
Partially
Resolved
0xa719cb79af...9de24
Token Standard
Functions
Verified Contract
// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.9;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";import "../../safeguard/Ownable.sol";/** * @title Example Multi-Bridge Pegged ERC20 token */contract MultiBridgeToken is ERC20, Ownable { struct Supply { uint256 cap; uint256 total; } mapping(address => Supply) public bridges; // bridge address -> supply uint8 private immutable _decimals; event BridgeSupplyCapUpdated(address bridge, uint256 supplyCap); constructor( string memory name_, string memory symbol_, uint8 decimals_ ) ERC20(name_, symbol_) { _decimals = decimals_; } /** * @notice Mints tokens to an address. Increases total amount minted by the calling bridge. * @param _to The address to mint tokens to. * @param _amount The amount to mint. */ function mint(address _to, uint256 _amount) external returns (bool) { Supply storage b = bridges[msg.sender]; require(b.cap > 0, "invalid caller"); b.total += _amount; require(b.total <= b.cap, "exceeds bridge supply cap"); _mint(_to, _amount); return true; } /** * @notice Burns tokens for msg.sender. * @param _amount The amount to burn. */ function burn(uint256 _amount) external returns (bool) { _burn(msg.sender, _amount); return true; } /** * @notice Burns tokens from an address. Decreases total amount minted if called by a bridge. * Alternative to {burnFrom} for compatibility with some bridge implementations. * See {_burnFrom}. * @param _from The address to burn tokens from. * @param _amount The amount to burn. */ function burn(address _from, uint256 _amount) external returns (bool) { return _burnFrom(_from, _amount); } /** * @notice Burns tokens from an address. Decreases total amount minted if called by a bridge. * See {_burnFrom}. * @param _from The address to burn tokens from. * @param _amount The amount to burn. */ function burnFrom(address _from, uint256 _amount) external returns (bool) { return _burnFrom(_from, _amount); } /** * @dev Burns tokens from an address, deducting from the caller's allowance. * Decreases total amount minted if called by a bridge. * @param _from The address to burn tokens from. * @param _amount The amount to burn. */ function _burnFrom(address _from, uint256 _amount) internal returns (bool) { Supply storage b = bridges[msg.sender]; if (b.cap > 0 || b.total > 0) { // set cap to 1 would effectively disable a deprecated bridge's ability to burn require(b.total >= _amount, "exceeds bridge minted amount"); unchecked { b.total -= _amount; } } _spendAllowance(_from, msg.sender, _amount); _burn(_from, _amount); return true; } /** * @notice Returns the decimals of the token. */ function decimals() public view virtual override returns (uint8) { return _decimals; } /** * @notice Updates the supply cap for a bridge. * @param _bridge The bridge address. * @param _cap The new supply cap. */ function updateBridgeSupplyCap(address _bridge, uint256 _cap) external onlyOwner { // cap == 0 means revoking bridge role bridges[_bridge].cap = _cap; emit BridgeSupplyCapUpdated(_bridge, _cap); } /** * @notice Returns the owner address. Required by BEP20. */ function getOwner() external view returns (address) { return owner(); }}
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../../safeguard/Ownable.sol";
/**
* @title Example Multi-Bridge Pegged ERC20 token
*/
contract MultiBridgeToken is ERC20, Ownable {
struct Supply {
uint256 cap;
uint256 total;
}
mapping(address => Supply) public bridges; // bridge address -> supply
uint8 private immutable _decimals;
event BridgeSupplyCapUpdated(address bridge, uint256 supplyCap);
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) ERC20(name_, symbol_) {
_decimals = decimals_;
* @notice Mints tokens to an address. Increases total amount minted by the calling bridge.
* @param _to The address to mint tokens to.
* @param _amount The amount to mint.
function mint(address _to, uint256 _amount) external returns (bool) {
Supply storage b = bridges[msg.sender];
require(b.cap > 0, "invalid caller");
b.total += _amount;
require(b.total <= b.cap, "exceeds bridge supply cap");
_mint(_to, _amount);
return true;
* @notice Burns tokens for msg.sender.
* @param _amount The amount to burn.
function burn(uint256 _amount) external returns (bool) {
_burn(msg.sender, _amount);
* @notice Burns tokens from an address. Decreases total amount minted if called by a bridge.
* Alternative to {burnFrom} for compatibility with some bridge implementations.
* See {_burnFrom}.
* @param _from The address to burn tokens from.
function burn(address _from, uint256 _amount) external returns (bool) {
return _burnFrom(_from, _amount);
function burnFrom(address _from, uint256 _amount) external returns (bool) {
* @dev Burns tokens from an address, deducting from the caller's allowance.
* Decreases total amount minted if called by a bridge.
function _burnFrom(address _from, uint256 _amount) internal returns (bool) {
if (b.cap > 0 || b.total > 0) {
// set cap to 1 would effectively disable a deprecated bridge's ability to burn
require(b.total >= _amount, "exceeds bridge minted amount");
unchecked {
b.total -= _amount;
_spendAllowance(_from, msg.sender, _amount);
_burn(_from, _amount);
* @notice Returns the decimals of the token.
function decimals() public view virtual override returns (uint8) {
return _decimals;
* @notice Updates the supply cap for a bridge.
* @param _bridge The bridge address.
* @param _cap The new supply cap.
function updateBridgeSupplyCap(address _bridge, uint256 _cap) external onlyOwner {
// cap == 0 means revoking bridge role
bridges[_bridge].cap = _cap;
emit BridgeSupplyCapUpdated(_bridge, _cap);
* @notice Returns the owner address. Required by BEP20.
function getOwner() external view returns (address) {
return owner();
The "MultiBridgeToken" Solidity smart contract is an ERC-20 token implementation that extends functionality for bridge interactions. It features minting and burning functions, allowing token creation and destruction. The contract maintains a mapping of bridge addresses to supply data, including caps and totals. The owner can update bridge supply caps, and the contract ensures cap adherence during minting.
It inherits from OpenZeppelin's ERC-20 and includes an "Ownable" component for ownership control. With compatibility for various bridge implementations, this contract facilitates token management and interaction within a multi-bridge ecosystem.
In the provided Solidity smart contract, the following privileged roles and their associated capabilities can be identified:Owner Role:
Bridge Roles:
These roles define the access control within the contract, with the owner having overarching control, and specific addresses designated as bridges having the ability to mint and burn tokens within the specified constraints. The contract aims to facilitate controlled token management, particularly in a multi-bridge environment.
function _burnFrom(address _from, uint256 _amount) internal returns (bool) { Supply storage b = bridges[msg.sender]; if (b.cap > 0 || b.total > 0) { // set cap to 1 would effectively disable a deprecated bridge's ability to burn require(b.total >= _amount, "exceeds bridge minted amount"); unchecked { b.total -= _amount; } } _spendAllowance(_from, msg.sender, _amount); _burn(_from, _amount); return true; }
Location in code: Inside the _burnFrom functionLine number: 152-176Description: The _burnFrom function does not utilize the ReentrancyGuard mechanism to prevent reentrancy attacks. An attacker might exploit this vulnerability to manipulate the contract state during execution.
function updateBridgeSupplyCap(address _bridge, uint256 _cap) external onlyOwner { // cap == 0 means revoking bridge role bridges[_bridge].cap = _cap; emit BridgeSupplyCapUpdated(_bridge, _cap); }
Location in code: Inside the updateBridgeSupplyCap functionLine number: 202-210Description: The updateBridgeSupplyCap function lacks input validation for the bridge address. Without proper validation, an incorrect input may lead to unintended changes in the supply cap.
function burn(uint256 _amount) external returns (bool) { _burn(msg.sender, _amount); return true; }//97
function burn(address _from, uint256 _amount) external returns (bool) { return _burnFrom(_from, _amount); }//118
Location in code: Inside the burn and burn(address _from, uint256 _amount) functionsLine number: 97 and 118Description: The burn functions do not emit events upon successful execution, making it challenging for external systems to track token burns.
function mint(address _to, uint256 _amount) external returns (bool) { Supply storage b = bridges[msg.sender]; require(b.cap > 0, "invalid caller"); b.total += _amount; require(b.total <= b.cap, "exceeds bridge supply cap"); _mint(_to, _amount); return true; }
Location in code: Inside the function mint(address _to, uint256 _amount) external returns (bool)Line number: 66-80Description: The minting function does not perform a proper overflow check when updating the total supply. An attacker could potentially exploit this vulnerability to mint an excessively large amount of tokens, causing an overflow.
function getOwner() external view returns (address) { return owner(); }
Location in code: Inside the getOwner functionLine number: 219-223Description: The function getOwner duplicates functionality provided by the inherited owner() function. Consider removing redundant functions to simplify the contract.
Our industry-leading audit methodology and tooling includes a review of your code’s logic, with a mathematical approach to ensure your program works as intended.