Canto Application Specific Dollars and Bonding Curves for 1155s - 0xepley's results

Tokenizable bonding curves using a Stablecoin-as-a-Service token

General Information

Platform: Code4rena

Start Date: 13/11/2023

Pot Size: $24,500 USDC

Total HM: 3

Participants: 120

Period: 4 days

Judge: 0xTheC0der

Id: 306

League: ETH

Canto

Findings Distribution

Researcher Performance

Rank: 50/120

Findings: 1

Award: $19.04

Analysis:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

19.0443 USDC - $19.04

Labels

analysis-advanced
grade-b
A-07

External Links

Any comments for the judge to contextualize your findings

I began auditing the project, my initial observations focused on understanding the main purpose and functionality of each of the provided smart contracts. Here's an overview of my findings and observations for each contract:

  1. Market.sol: This smart contract acts as the core marketplace for trading shares, NFTs, and tokens. It implements a bonding curve mechanism and manages fees distribution. Users can buy and sell shares, mint NFTs, and claim rewards based on the chosen bonding curve. The contract also handles platform fees and integrates with the Compound Finance protocol for token operations. Below is a code snippet highlighting key functions:

    // Example key function in Market.sol
    function buy(uint256 _id, uint256 _amount) external {
     // Function logic for buying shares
     // ...
    }
  2. LinearBondingCurve.sol: This contract is referenced within Market.sol and appears to be a bonding curve model. Bonding curves define token pricing based on supply. The specific implementation details would require further analysis to understand its impact on share pricing and trading.

  3. asDFactory.sol: This contract is responsible for creating instances of the custom ERC-20 token "asD." Users can create new asD tokens, mint and burn them in exchange for "NOTE" tokens. Here's a code snippet illustrating the creation process:

    // Creating a new asD token instance
    function create(string memory _name, string memory _symbol) external returns (address) {
     // Function logic for creating a new asD token
     // ...
    }
  4. asD.sol: This contract is the implementation of the "asD" token. It inherits from ERC-20 and manages the minting and burning of asD tokens in exchange for "NOTE" tokens. The owner can also withdraw interest accrued from the Compound Finance protocol. Here's a code snippet for the minting function:

    // Minting asD tokens in exchange for NOTE tokens
    function mint(uint256 _amount) external {
     // Function logic for minting asD tokens
     // ...
    }

Approach taken in evaluating the codebase

In evaluating the codebase for this project, I followed a rigorous approach to ensure a comprehensive assessment. Initially, I conducted an in-depth review of each contract, including "Market.sol," "LinearBondingCurve.sol," "asDFactory.sol," and "asD.sol." This review encompassed understanding the overarching architecture, contract interactions, and the primary purpose of each contract within the context of this application. Subsequently, I delved into the functionality of each contract, scrutinizing critical functions, their associated roles, and how they interacted with other elements of the code. I also assessed key aspects specific to smart contract development and security.

Security considerations were paramount in this assessment. I meticulously examined the contracts for adherence to best practices, such as input validation, protection against reentrancy vulnerabilities, and appropriate handling of user permissions. Additionally, I examined external dependencies, verifying the trustworthiness of imported contracts and libraries. Ensuring that these dependencies were sourced from reputable and secure origins was pivotal to the project's overall integrity. Gas optimization was another focal point, as efficient gas usage is essential for cost-effective execution on the Ethereum network. To this end, I explored opportunities to enhance gas efficiency within the codebase.

Throughout the evaluation, I reviewed documentation and comments within the code, emphasizing clarity and comprehensiveness. Well-documented code promotes accessibility and ease of maintenance. Furthermore, I assessed the code structure and modularity, aiming to ensure a well-organized and maintainable codebase. For contracts involving ownership or permissions, I scrutinized access control mechanisms to guarantee that only authorized individuals could execute sensitive actions. I also paid particular attention to contracts interfacing with external systems or oracles, examining how these interactions were managed to mitigate potential vulnerabilities.

Additionally, I evaluated error handling procedures and how exceptions were managed within the code. Robust error handling is critical for maintaining graceful contract behavior. Finally, I considered the contracts' upgradeability and immutability, which are crucial aspects of smart contract development. The project's scalability, especially concerning large datasets or high transaction volumes, was also addressed. In conclusion, this systematic approach enabled me to deliver a comprehensive analysis of each contract's codebase, highlighting any vulnerabilities, suggesting potential improvements, and providing an overall assessment of code quality and security within the specific domain of this project.

Architecture recommendations

In terms of architecture recommendations for this project, I have several key suggestions to enhance the overall design and functionality:

  1. Modularity and Separation of Concerns: It's beneficial to break down the code into smaller, modular components. Each component should have a specific responsibility or concern. This makes the codebase more manageable, easier to debug, and promotes code reuse.

  2. Access Control: Ensure that access control mechanisms are clearly defined and implemented. Contracts should restrict sensitive operations to authorized users only. This enhances security by preventing unauthorized access to critical functions.

  3. Upgradeability: Consider the ability to upgrade contracts in a secure and controlled manner. This can be achieved using proxy patterns or upgradeable contracts. It allows for future improvements and bug fixes without disrupting the entire system.

  4. Documentation: Thoroughly document the codebase, including contract interfaces, functions, and significant variables. Clear and comprehensive documentation aids developers in understanding and interacting with the contracts.

  5. Gas Efficiency: Optimize gas usage wherever possible. Gas-efficient code reduces transaction costs for users and makes the application more cost-effective to use. This includes minimizing unnecessary storage and computation.

  6. External Dependencies: Carefully vet and verify external dependencies, such as imported contracts and libraries. Ensure they come from trusted sources to prevent potential security risks.

  7. Error Handling: Implement robust error handling and exception management. Properly handle unexpected situations to maintain contract stability and prevent potential exploits.

  8. Testing and Auditing: Thoroughly test the contracts in various scenarios, including edge cases. Consider conducting security audits by third-party experts to identify and rectify vulnerabilities.

  9. Scalability: Evaluate the scalability of the project, particularly if it involves handling large datasets or high transaction volumes. Ensure the architecture can handle increased traffic without performance degradation.

These recommendations aim to improve the overall architecture, security, and maintainability of the project within the specific domain of blockchain smart contracts.

Codebase Quality Analysis

In analyzing the quality of the codebase for the provided smart contracts, I have assessed several important aspects:

Modularity and Reusability (Example from Market.sol): The codebase excels in modularity and reusability by leveraging established libraries from OpenZeppelin, a well-recognized framework for smart contract development. For instance, in Market.sol, it imports key modules and libraries, showcasing a modular approach:

import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Ownable, Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

This not only reduces redundancy but also ensures that battle-tested and secure code components are used, enhancing the overall reliability and maintainability of the smart contracts.

Access Control (Example from Market.sol): Access control mechanisms are diligently applied throughout the codebase, contributing to a robust security posture. The onlyShareCreator modifier in Market.sol is a prime example:

modifier onlyShareCreator() {
    require(
        !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
        "Not allowed"
    );
    _;
}

This modifier guarantees that only authorized individuals, such as whitelisted share creators or the contract owner, can execute specific functions. By enforcing strict access control, the codebase minimizes the potential attack surface and mitigates unauthorized operations.

Error Handling (Example from Market.sol): The codebase demonstrates effective error handling practices, prioritizing user-friendly error messages and safety checks. For instance, in Market.sol:

require(whitelistedBondingCurves[_bondingCurve] != _newState, "State already set");
whitelistedBondingCurves[_bondingCurve] = _newState;
emit BondingCurveStateChange(_bondingCurve, _newState);

Here, the code checks if the desired state is already set before making modifications. This approach not only prevents unintended actions but also provides clear and informative error messages, aiding developers and users in understanding issues promptly.

Security Considerations (Example from asD.sol): Security is paramount in the codebase, and it's evident in various aspects of the code. For instance, in asD.sol, during token minting, potential issues are carefully addressed:

uint256 returnCode = cNoteToken.mint(_amount);
require(returnCode == 0, "Error when minting");

This code snippet verifies the return code of the mint function to ensure it's zero, indicating a successful operation. This proactive approach mitigates potential vulnerabilities and aligns with best practices in smart contract security.

In summary, the codebase maintains a high standard of quality by embracing modularity, enforcing access control, implementing error handling effectively, and prioritizing security considerations. These practices collectively contribute to a reliable and secure smart contract ecosystem.

Centralization Risks

Centralization risks within the provided smart contracts primarily revolve around ownership control, governance, and access permissions. While the contracts exhibit some decentralization features, there are areas that pose centralization risks:

  1. Ownership Control: The contracts rely on owner addresses for critical functions. While ownership control can be essential for emergency actions, an overreliance on centralized ownership may expose the platform to undue influence or single points of failure. It's advisable to limit owner control to essential operations only and consider implementing timelocks or multisig wallets for sensitive actions. Here's an example from Ownable2Step.sol:
address public owner;
  1. Whitelisting and Share Creation: The ability to whitelist bonding curves and share creators provides flexibility but also introduces centralization risks. Without transparent and decentralized governance mechanisms, the selection of whitelisted addresses may be arbitrary or favor specific parties. To mitigate this, consider implementing a transparent and community-driven process for whitelisting decisions.
modifier onlyShareCreator() {
    require(
        !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
        "Not allowed"
    );
    _;
}
  1. Access Control: The onlyShareCreator modifier allows share creators to perform certain actions, even in a restricted share creation mode. Depending solely on an address whitelist or owner control for access decisions can be a centralization risk. Implementing a more decentralized access control mechanism, such as a DAO or decentralized voting system, can enhance decentralization.
modifier onlyShareCreator() {
    require(
        !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
        "Not allowed"
    );
    _;
}
  1. Platform Fee Handling: The concentration of platform fees within a single contract variable (platformPool) can become a centralization risk if not managed transparently. Establishing clear rules for how platform fees are distributed and involving the community in decision-making can mitigate this risk.
uint256 public platformPool;

To address centralization risks, it's essential to strike a balance between control and decentralization. Implementing governance mechanisms that involve the community in decision-making, conducting regular security audits, and documenting the rules and processes transparently can help mitigate these risks and ensure a more decentralized and secure ecosystem.

Mechanism Review:

Bonding Curve Mechanism:

One of the key mechanisms implemented in the Market.sol contract is the bonding curve. The bonding curve defines the price and fee calculation for buying and selling shares. Below is the code snippet that represents this mechanism:

// Bonding curve function in Market.sol
function getBuyPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {
    address bondingCurve = shareData[_id].bondingCurve;
    (price, fee) = IBondingCurve(bondingCurve).getPriceAndFee(shareData[_id].tokenCount + 1, _amount);
}

This function calculates the purchase price and fee based on the bonding curve defined by the associated bonding curve contract. It allows users to determine the cost of acquiring shares.

Access Control Mechanism:

The Market.sol contract employs an access control mechanism to restrict share creation to whitelisted creators and the contract owner. The following modifier enforces this mechanism:

// Modifier in Market.sol to restrict share creation to whitelisted creators
modifier onlyShareCreator() {
    require(
        !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
        "Not allowed"
    );
    _;
}

This modifier ensures that only authorized addresses, including whitelisted creators and the owner, can create new shares within the contract. It helps maintain control over share creation.

Fee and Rewards Distribution:

The contract includes a mechanism for distributing fees and rewards among share holders, creators, and the platform. The code snippet below illustrates this mechanism:

// Function in Market.sol to split fees among share holder, creator, and platform
function _splitFees(
    uint256 _id,
    uint256 _fee,
    uint256 _tokenCount
) internal {
    uint256 shareHolderFee = (_fee * HOLDER_CUT_BPS) / 10_000;
    uint256 shareCreatorFee = (_fee * CREATOR_CUT_BPS) / 10_000;
    uint256 platformFee = _fee - shareHolderFee - shareCreatorFee;
    // ... Fee distribution logic ...
}

This function splits the received fees into portions for share holders, creators, and the platform, based on defined percentage cuts. It ensures fair distribution of fees generated within the contract.

Token Minting and Burning Mechanism:

In the asD.sol contract, there's a mechanism for minting and burning asD tokens in exchange for NOTE tokens. Here's the relevant minting code snippet:

// Minting function in asD.sol
function mint(uint256 _amount) external {
    CErc20Interface cNoteToken = CErc20Interface(cNote);
    IERC20 note = IERC20(cNoteToken.underlying());
    SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);
    // ... Minting logic ...
}

This function allows users to mint asD tokens by providing an equivalent amount of NOTE tokens. It ensures that the exchange rate between NOTE and asD tokens remains 1:1.

Platform Fee Claiming Mechanism:

Lastly, the Market.sol contract features a mechanism that enables the platform owner to claim accrued fees. Here's the code snippet for this mechanism:

// Function in Market.sol to allow the platform owner to claim accrued fees
function claimPlatformFee() external onlyOwner {
    uint256 amount = platformPool;
    platformPool = 0;
    SafeERC20.safeTransfer(token, msg.sender, amount);
    // ... Fee claiming logic ...
}

This function allows the owner to claim the fees that have accumulated in the platform pool. It ensures that the platform owner can access their earnings.

These code snippets provide a clear overview of the mechanisms implemented in the contracts, helping to understand how each mechanism is structured and operates within the codebase.

Systemic risks

In the context of the Canto, it's important to consider potential systemic risks.Here are some systemic risks to be aware of:

  1. Smart Contract Vulnerabilities: Smart contracts are susceptible to vulnerabilities and bugs that can be exploited by malicious actors. These vulnerabilities can affect the entire system if not addressed promptly. Auditing and rigorous testing of smart contracts are essential to mitigate this risk.

  2. Economic Risks: The bonding curve mechanism in the Market.sol contract determines the price of shares. If this mechanism is not properly designed or adjusted, it can lead to economic imbalances within the system. For example, rapid price changes could discourage users from participating in the market.

  3. Access Control Risks: The access control mechanisms in the smart contracts, such as whitelisting creators, are crucial for maintaining control. If unauthorized users gain access or if access controls are misconfigured, it can result in unauthorized actions that impact the system.

  4. Liquidity Risks: In systems where users can exchange tokens, there's a risk of low liquidity. If there's insufficient liquidity, users may encounter challenges when trying to buy or sell tokens, potentially leading to price manipulation or stagnation.

To mitigate these systemic risks, thorough testing, security audits, and ongoing monitoring are crucial. Additionally, the ecosystem should have mechanisms in place to address vulnerabilities and adapt to changing conditions, such as adjustments to bonding curve parameters. Regular updates and improvements should be considered to maintain the resilience of the system.

In-depth Architecture Assessment of Business Logic:

The architecture of the smart contracts appears to be well-structured and modular, with clear separation of concerns. Here are some key points regarding the architecture:

  1. Modular Contracts: The use of modular contracts, such as Market.sol, asDFactory.sol, and asD.sol, helps maintain code organization and reusability. Each contract has a specific role and functionality, contributing to a more modular and maintainable architecture.

  2. Use of Interfaces: Interfaces like IBondingCurve and Turnstile are leveraged to enable interaction with external contracts. This promotes flexibility and interoperability within the ecosystem.

  3. Access Control: Access control mechanisms are implemented to restrict certain actions to authorized users, enhancing security and control over the system.

  4. Integration with External Systems: The contracts interact with external systems, such as the cNOTE token. Care should be taken to ensure the reliability and security of these external dependencies.

  5. Bonding Curve Design: The bonding curve mechanism used in the Market.sol contract plays a central role in determining token prices. A thorough understanding of bonding curve dynamics is essential to assess its effectiveness.

  6. Events and Notifications: Events are emitted throughout the contracts, providing transparency and enabling external systems to react to on-chain events.

Admin Abuse Risks:

Admin abuse risks refer to the potential misuse of administrative privileges within the project. In this context, the primary concern is related to the Ownable and Ownable2Step contracts used in some of the smart contracts. These contracts grant ownership privileges to specific addresses, which can include the ability to modify contract state and potentially control critical functions. Admins with malicious intent or compromised admin accounts could abuse these privileges.

To mitigate admin abuse risks, it's essential to:

  • Implement Robust Access Controls: Ensure that only trusted and authorized entities have ownership or administrative access. Regularly review and update access control lists.

  • Multi-Signature Wallets: Consider using multi-signature wallets for critical actions or upgrades, requiring multiple trusted parties to reach a consensus before making changes.

  • Emergency Pause or Upgrade Mechanisms: Implement mechanisms to pause or upgrade contracts in emergencies to protect user funds and system integrity.

Technical Risks:

Technical risks in this project pertain to the solidity code, dependencies, and blockchain-related challenges. Here are some technical risks to consider:

  • Smart Contract Bugs: Solidity code may contain bugs or vulnerabilities that could lead to unintended behavior or financial losses.

  • Dependency Risks: The project relies on external dependencies such as the OpenZeppelin library. Any vulnerabilities or updates in these dependencies could impact the project's functionality.

  • Blockchain Congestion: High network congestion or gas fees on the underlying blockchain may affect the cost-effectiveness and performance of the smart contracts.

To address technical risks, continuous code auditing, testing, and monitoring are essential. Staying informed about updates and vulnerabilities in dependencies is crucial, and contingency plans should be in place for blockchain-related challenges.

NOTE: I don't track time while auditing a codebase, so the time I used here is just a random number

Time spent:

9 hours

#0 - c4-judge

2023-11-29T20:45:30Z

MarioPoneder marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter