Skip to content

This repository is dedicated to the smart contract auditing using our FTSmartAudit tool

Notifications You must be signed in to change notification settings

LLMSmartAudit/FTSmartAudit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Specialized Models for Smart Contract Auditing!

🕌 FTAudit Ecosystem

FTAudit Ecosystem

Our Ecosystem aims to provide a comprehensive solution for smart contract auditing. It includes:

  • A set of specialized models
  • A user-friendly interface
  • A powerful backend to support the entire auditing process

By leveraging these specialized models, our Ecosystem helps users quickly and accurately identify potential vulnerabilities in their smart contracts, providing valuable insights and recommendations for improvement.

✨ Run Specialized Models

All notebooks are beginner friendly! Add your smart contract dataset, click "Run All", and you'll get a auditing report. Use can use our colab scripts or your local devices.

Model List Free Notebooks Model Source
FTAudit-Llama3 (8B) ▶️ Start for free ⬇Download
FTAudit-Mistral (7B) ▶️ Start for free ⬇Download
FTAudit-Gemma (7B) ▶️ Start for free ⬇Download
FTAudit-Codegemma (7B) ▶️ Start for free ⬇Download

We also fine-tuning other kinds of models for smart contract auditing.

Model List Model Source
FTAudit-Vuln-Llama3 (8B) ⬇Download
FTAudit-Vuln-Mistral (7B) ⬇Download
FTAudit-Vuln-Gemma (7B) ⬇Download
FTAudit-Vuln-Codegemma (7B) ⬇Download

In our early research, we also fine-tune other models:

Model List Model Source
FTAudit-Codellama-v0.2 (13B) ⬇Download
FTAudit-Codellama (7B) ⬇Download
FTAudit-Llama2 (7B) ⬇Download

🦙 FTAudit.ai News

🔗 Links and Resources

Type Links
📚 Documentation & Wiki Read Our Wiki
🥇 Benchmarking Details
🌐 Evaluation Reports

🐞 Vulnerability Categories

Smart contract vulnerabilities can be divided into two categories: machine-auditable and machine-unauditable. Machine-auditable vulnerabilities can be identified by conventional tools, whereas machine-unauditable vulnerabilities require human auditors for detection. In our study, we label these machine-auditable vulnerabilities as “detectable vulnerabilities” and the machine-unauditable ones as “undetectable vulnerabilities.” Our fine-tuning dataset incorporates both types, comprising a total of 112 distinct vulnerability labels.

🔍 Detectable Vulnerabilities

These vulnerabilities can be identified by conventional automated tools.

Vulnerability Type Description
Reentrancy Allows a function to be interrupted and re-entered before completion
Predictable Randomness Use of deterministic values for random number generation
Integer Overflow Arithmetic operations exceeding the max value for the data type
Unchecked Low-Level Calls Failure to check return values of low-level function calls
Front-running Exploitation of transaction ordering in the blockchain
Denial-of-Service Preventing legitimate users from accessing the contract
Access Control Improper restrictions on who can execute certain functions
Time Manipulation Exploitation of block timestamp dependencies
Uninitialized Struct Using struct variables without proper initialization
Short Address Exploiting EVM padding behavior in function parameters

🕵️ Undetectable Vulnerabilities

These vulnerabilities require human auditors for detection due to their complexity or context-dependent nature.

  1. Price Manipulation
  2. Lack of Input Validation
  3. Hidden Ownership Change
  4. Unrestricted Initialization
  5. State Manipulation
  6. Misuse of msg.value within a loop
  7. Incorrect Allowance Update Logic
  8. Data Corruption
  9. Lack of Withdrawal Function
  10. Missing Authorization Checks
  11. Storage Error
  12. Hash Collision
  13. Misuse of shr without Context
  14. Uninitialized Return Variable
  15. Constructor Misdeclaration
  16. Potential Unintended Behavior
  17. Missing onlyOwner Modifier
  18. Shadowing State Variable
  19. Uninitialized State Variable
  20. Improper Struct Initialization
  21. Improper Initialization Check
  22. Withdrawal Functions without Proper Access Control
  23. Direct Modification of Array Length
  24. Misuse of Assembly return
  25. Unchecked Transfer
  26. Unsafe Enum Conversion
  27. Impracticality of Exact Match
  28. Lack of Functionality
  29. Mapping Deletion
  30. Shadow State Variable
  31. Misinterpretation of Unsigned Integer Comparison
  32. Redundant Condition
  33. Integer Division Resulting in Loss of Precision
  34. Atomicity and Ordering
  35. Constructor Inheritance
  36. Constructor Execution Order
  37. Unused Return
  38. Overshadowing Built-in XX
  39. Incorrect Data Type
  40. Uninitialized Function Pointer
  41. Use of Variable before Declaration
  42. Improper Scope of Variable
  43. Incorrect Scope of Variable max
  44. Incorrect Constructor Call
  45. Unbounded Loop with External Calls
  46. Missing State Variable Declarations
  47. Incorrect Increment Operation
  48. Incorrect Operation
  49. Unbounded Gas for External Calls
  50. Incorrect Use of assert
  51. Unnecessary Comparison
  52. Deprecated Features
  53. Unpredictable Initialization
  54. Redundant Statements and Syntax Errors
  55. Incomplete Implementation
  56. Inefficient State Modifications in a Loop
  57. Misuse of Mapping Getter
  58. Cancellation Authority
  59. Discrepancy in Balance Calculation
  60. Dependence on External Data
  61. Complexity
  62. Funding Rate Calculation Precision
  63. Minting Permissions
  64. Flash Loan Fee Manipulation
  65. Centralized Risk
  66. Single Points of Failure
  67. Potential Ownership Hijacking
  68. Insecure Ownership Deletion
  69. Constructor Syntax
  70. Uninitialized creator Variable
  71. Incorrect Require Condition in withdraw Function
  72. Uninitialized Constructor
  73. Missing Zero-Address Check
  74. Lack of Access Control for Sensitive Functions
  75. Signature Malleability
  76. Incorrect Signature Verification
  77. Potential Inconsistency
  78. Oracle Manipulation
  79. Oracle Downtime
  80. Missing Nonce Increment
  81. Off-chain Signature
  82. Replay Attack
  83. Owner's Absolute Control Over Critical Functions
  84. Misuse of msg.sig for Authorization
  85. Unchecked Return Values for ERC20 Transfers
  86. Potential for Inaccurate Data
  87. No Validation of the Price Source
  88. Lack of Proper Error Handling in SafeMath Library
  89. Missing SafeMath Functions for Division
  90. Unchecked Division by Zero
  91. Overflow and Underflow in transfer and transferFrom Functions
  92. Single Point of Failure
  93. Deprecated throw
  94. Hardcoded Timestamp
  95. Use of Deprecated Functions
  96. Logic errors in state machine implementations
  97. Potential Token Lockup
  98. Unlimited Token Approval
  99. Improper Event Emission
  100. Incorrect Handling of ETH Transfers
  101. Lack of Pull Payment Implementation
  102. Incorrect use of fallback functions

Newly Discovered Vulnerabilities:

Our models have successfully identified 13 vulnerabilities across 4 different types that were not detected in the audit reports from Code4rena.

📜 Full List of Undetected Vulnerabilities

  • Potential Token Lockup:

    -- In yVault.sol, the earn function transfers the available tokens to the controller without any checks or restrictions. If the controller contract is not properly implemented or has a vulnerability, it could potentially lock up the tokens and make them irretrievable.

function earn() external {
    uint256 _bal = available();
    token.safeTransfer(address(controller), _bal);
    controller.earn(address(token), _bal);
}

-- The mint function of sYETIToken.sol, sends the YETI tokens to the sYETI contract using the sendToSYETI function of the yetiToken contract. If the yetiToken contract has a vulnerability or is not properly implemented, it could potentially lock up the tokens and make them irretrievable.

function mint(uint256 amount) public returns (bool) {
    User memory user = users[msg.sender];
    uint256 shares = totalSupply == 0 ? amount : (amount * totalSupply) / effectiveYetiTokenBalance;
    user.balance += shares.to128();
    user.lockedUntil = (block.timestamp + LOCK_TIME).to128();
    users[msg.sender] = user;
    totalSupply += shares;
    yetiToken.sendToSYETI(msg.sender, amount);
    effectiveYetiTokenBalance = effectiveYetiTokenBalance.add(amount);
    emit Transfer(address(0), msg.sender, shares);
    return true;
}
  • Insufficient Input Validation:

    In sYETIToken.sol, the setTransferRatio function checks if the new ratio is zero but does not check for overflow. A malicious owner could set a very high transferRatio, potentially manipulating the rebasing mechanism.

function mint(uint256 amount) public returns (bool) {
    User memory user = users[msg.sender];
    uint256 shares = totalSupply == 0 ? amount : (amount * totalSupply) / effectiveYetiTokenBalance;
    user.balance += shares.to128();
    user.lockedUntil = (block.timestamp + LOCK_TIME).to128();
    users[msg.sender] = user;
    totalSupply += shares;
    yetiToken.sendToSYETI(msg.sender, amount);
    effectiveYetiTokenBalance = effectiveYetiTokenBalance.add(amount);
    emit Transfer(address(0), msg.sender, shares);
    return true;
}
  • Unlimited Token Approval:

    In the initialize function of IdeleYieldSource.sol, the contract approves the idleToken to spend an unlimited amount of underlyingAsset tokens using safeApprove with type(uint256).max. This poses a risk if the idleToken contract is compromised or has a vulnerability that allows it to drain the approved tokens.

    function initialize(address _idleToken) public initializer {
        __Ownable_init();
        idleToken = _idleToken;
        underlyingAsset = IIdleToken(idleToken).token();
        IERC20Upgradeable(underlyingAsset).safeApprove(idleToken, type(uint256).max);
        emit IdleYieldSourceInitialized(idleToken);
    }

In the _sendForReceiver function of NFTXSimpleFeeDistributor.sol, the contract approves the receiver contract to spend an unlimited amount of tokens using IERC20Upgradeable(_vault).approve(_receiver.receiver, amountToSend). This practice is generally discouraged as it poses a security risk if the receiver contract is compromised or behaves maliciously.

  function _sendForReceiver(FeeReceiver memory _receiver, uint256 _vaultId, address _vault, uint256 amountToSend) internal virtual returns (bool) {
    if (_receiver.isContract) {
      IERC20Upgradeable(_vault).approve(_receiver.receiver, amountToSend);
      
      bytes memory payload = abi.encodeWithSelector(INFTXLPStaking.receiveRewards.selector, _vaultId, amountToSend);
      (bool success, ) = address(_receiver.receiver).call(payload);
      return success && IERC20Upgradeable(_vault).allowance(address(this), _receiver.receiver) == 0;
    } else {
      IERC20Upgradeable(_vault).safeTransfer(_receiver.receiver, amountToSend);
    }
  }

The _maxApprove function of SingleTokenJoinV2.sol, grants unlimited token approval to the specified spender if the current allowance is less than the contract's token balance. This could potentially allow the approved spender to transfer more tokens than intended. The contract approves unlimited token spending for each token in the basket using _maxApprove before calling joinPool. If any of the tokens in the basket are malicious or have a vulnerability, they could potentially drain the approved tokens from the contract.

The Vault.sol contract does not handle the return values of some external function calls. For example, in the earn function, the return value of _controller.earn is not checked. If the external function fails or returns an unexpected value, it could lead to inconsistencies or unexpected behavior.

The lockWithPermit function of XDEFIDistribution.sol contract, uses the permit function of the IEIP2612 interface to approve the token transfer. However, there is no check to ensure that the permit call was successful before proceeding with the token transfer.

  • Unprotected Function:

Unprotected setMinter Function: The setMinter function of Position.sol contract, allows the contract owner to set any address as a minter. However, there is no mechanism to prevent the owner from accidentally or maliciously setting an unintended address as a minter.

Unprotected setParams() Function: The setParams() function of USDV.sol contract, allows the DAO to set the blockDelay parameter. However, there are no restrictions on the value that can be set. An attacker controlling the DAO can set an arbitrary blockDelay, potentially disrupting the contract's behavior or enabling attacks. It is important to validate and restrict the range of values that can be set for critical parameters.

Unprotected setMin Function: The setMin function of Vault.sol, allows the strategist to set the min value, which determines the minimum amount of tokens available for earning. However, there is no upper limit or validation on the _min value. A malicious strategist could set a very high min value, effectively locking up a significant portion of the vault's tokens.

Unprotected migrate function: The migrate function of MapleLoan.sol, allows the factory contract to migrate the contract to a new implementation. However, there are no restrictions on the migrator_ address or the arguments_ passed to the function. This could lead to unauthorized migration or loss of funds if not properly implemented.

🏋🏿Training Details

Training Loss Training Loss Graph
GPU Memory Usage GPU Power Consumption

😘 Thank You to

  • Unsloth AI for providing the Faster Interface Plan, accelerating our evaluations.

Citation

Feel free to cite us if you like ToolBench.

@misc{wei2024ftaudit,
      title={Leveraging Fine-Tuned Language Models for Efficient and Accurate Smart Contract Auditing}, 
      author={Zhiyuan Wei, Jing Sun, Zijian Zhang, Xianhao Zhang, Meng Li},
      year={2024},
      eprint={2410.13918},
      archivePrefix={arXiv},
      primaryClass={cs.AI}
}

About

This repository is dedicated to the smart contract auditing using our FTSmartAudit tool

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published