Halborn Logo

BTC Staking - CoreDAO


Prepared by:

Halborn Logo

HALBORN

Last Updated 04/17/2024

Date of Engagement by: March 11th, 2024 - March 22nd, 2024

Summary

100% of all REPORTED Findings have been addressed

All findings

5

Critical

0

High

0

Medium

1

Low

0

Informational

4


1. Introduction

The CoreDAO Team engaged Halborn to conduct a security assessment on their smart contracts beginning on 03/11/2024 and ending on 03/22/2024. The security assessment was scoped to the smart contracts provided in the GitHub repository. Commit hashes and further details can be found in the Scope section of this report.

2. Assessment Summary

Halborn was provided 2 weeks for the engagement and assigned 1 full-time security engineer to review the security of the smart contracts in scope. The engineer is a blockchain and smart contract security experts with advanced penetration testing and smart contract hacking skills, and deep knowledge of multiple blockchain protocols.

The purpose of the assessment is to:

    • Identify potential security issues within the smart contracts.

    • Ensure that smart contract functionality operates as intended.

In summary, Halborn identified some security that were mostly addressed by the CoreDAO team.

2.1 Test Approach and Methodology

Halborn performed a combination of manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy in regard to the scope of this assessment. While manual testing is recommended to uncover flaws in logic, process, and implementation; automated testing techniques help enhance coverage of the code and can quickly identify items that do not follow the security best practices. The following phases and associated tools were used during the assessment:

    • Research into architecture and purpose.

    • Smart contract manual code review and walkthrough.

    • Graphing out functionality and contract logic/connectivity/functions (solgraph).

    • Manual assessment of use and safety for the critical Solidity variables and functions in scope to identify any arithmetic related vulnerability classes.

    • Manual testing by custom scripts.

    • Static Analysis of security for scoped contract, and imported functions (slither).

    • Testnet deployment (Foundry).


2.2 Out-of-scope

    • External libraries and financial-related attacks.

    • New features/implementations after/with the remediation commit IDs.


3. RISK METHODOLOGY

Every vulnerability and issue observed by Halborn is ranked based on two sets of Metrics and a Severity Coefficient. This system is inspired by the industry standard Common Vulnerability Scoring System.
The two Metric sets are: Exploitability and Impact. Exploitability captures the ease and technical means by which vulnerabilities can be exploited and Impact describes the consequences of a successful exploit.
The Severity Coefficients is designed to further refine the accuracy of the ranking with two factors: Reversibility and Scope. These capture the impact of the vulnerability on the environment as well as the number of users and smart contracts affected.
The final score is a value between 0-10 rounded up to 1 decimal place and 10 corresponding to the highest security risk. This provides an objective and accurate rating of the severity of security vulnerabilities in smart contracts.
The system is designed to assist in identifying and prioritizing vulnerabilities based on their level of risk to address the most critical issues in a timely manner.

3.1 EXPLOITABILITY

Attack Origin (AO):
Captures whether the attack requires compromising a specific account.
Attack Cost (AC):
Captures the cost of exploiting the vulnerability incurred by the attacker relative to sending a single transaction on the relevant blockchain. Includes but is not limited to financial and computational cost.
Attack Complexity (AX):
Describes the conditions beyond the attacker’s control that must exist in order to exploit the vulnerability. Includes but is not limited to macro situation, available third-party liquidity and regulatory challenges.
Metrics:
EXPLOITABILIY METRIC (mem_e)METRIC VALUENUMERICAL VALUE
Attack Origin (AO)Arbitrary (AO:A)
Specific (AO:S)
1
0.2
Attack Cost (AC)Low (AC:L)
Medium (AC:M)
High (AC:H)
1
0.67
0.33
Attack Complexity (AX)Low (AX:L)
Medium (AX:M)
High (AX:H)
1
0.67
0.33
Exploitability EE is calculated using the following formula:

E=meE = \prod m_e

3.2 IMPACT

Confidentiality (C):
Measures the impact to the confidentiality of the information resources managed by the contract due to a successfully exploited vulnerability. Confidentiality refers to limiting access to authorized users only.
Integrity (I):
Measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of data stored and/or processed on-chain. Integrity impact directly affecting Deposit or Yield records is excluded.
Availability (A):
Measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability. This metric refers to smart contract features and functionality, not state. Availability impact directly affecting Deposit or Yield is excluded.
Deposit (D):
Measures the impact to the deposits made to the contract by either users or owners.
Yield (Y):
Measures the impact to the yield generated by the contract for either users or owners.
Metrics:
IMPACT METRIC (mIm_I)METRIC VALUENUMERICAL VALUE
Confidentiality (C)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Integrity (I)None (I:N)
Low (I:L)
Medium (I:M)
High (I:H)
Critical (I:C)
0
0.25
0.5
0.75
1
Availability (A)None (A:N)
Low (A:L)
Medium (A:M)
High (A:H)
Critical (A:C)
0
0.25
0.5
0.75
1
Deposit (D)None (D:N)
Low (D:L)
Medium (D:M)
High (D:H)
Critical (D:C)
0
0.25
0.5
0.75
1
Yield (Y)None (Y:N)
Low (Y:L)
Medium (Y:M)
High (Y:H)
Critical (Y:C)
0
0.25
0.5
0.75
1
Impact II is calculated using the following formula:

I=max(mI)+mImax(mI)4I = max(m_I) + \frac{\sum{m_I} - max(m_I)}{4}

3.3 SEVERITY COEFFICIENT

Reversibility (R):
Describes the share of the exploited vulnerability effects that can be reversed. For upgradeable contracts, assume the contract private key is available.
Scope (S):
Captures whether a vulnerability in one vulnerable contract impacts resources in other contracts.
Metrics:
SEVERITY COEFFICIENT (CC)COEFFICIENT VALUENUMERICAL VALUE
Reversibility (rr)None (R:N)
Partial (R:P)
Full (R:F)
1
0.5
0.25
Scope (ss)Changed (S:C)
Unchanged (S:U)
1.25
1
Severity Coefficient CC is obtained by the following product:

C=rsC = rs

The Vulnerability Severity Score SS is obtained by:

S=min(10,EIC10)S = min(10, EIC * 10)

The score is rounded up to 1 decimal places.
SeverityScore Value Range
Critical9 - 10
High7 - 8.9
Medium4.5 - 6.9
Low2 - 4.4
Informational0 - 1.9

4. SCOPE

Files and Repository
(a) Repository: core-genesis-contract
(b) Assessed Commit ID: eaf4a64
(c) Items in scope:
  • contracts/BtcLightClient.sol
  • contracts/CandidateHub.sol
  • contracts/PledgeAgent.sol
↓ Expand ↓
Out-of-Scope: Third-party libraries and dependencies, Economic attacks, Test and mock contacts
Remediation Commit ID:
Out-of-Scope: New features/implementations after the remediation commit IDs.

5. Assessment Summary & Findings Overview

Critical

0

High

0

Medium

1

Low

0

Informational

4

Security analysisRisk levelRemediation Date
Front-Running in delegateBtc FunctionMediumSolved - 03/22/2024
Lack of Dynamic Governance Control Over CLAIM_ROUND_LIMIT in PledgeAgent ContractInformationalAcknowledged
Missing Implementations in the IPledgeAgent Interface for BTC Delegation and Reward DistributionInformationalSolved - 03/22/2024
Typo in BtcExpireInfo Struct Mapping NameInformationalSolved - 03/24/2024
Lack of Reentrancy Protection in Public Functions transferBtc and claimBtcRewardInformationalAcknowledged

6. Findings & Tech Details

6.1 Front-Running in delegateBtc Function

// Medium

Description

The delegateBtc function, intended for users to delegate Bitcoin (BTC) to the Core blockchain, lacks mechanisms to prevent front-running attacks. This vulnerability arises from the function's design, which does not account for the potential for malicious actors to observe and preempt legitimate transactions in the mempool, potentially affecting the intended transaction outcomes. A successful front-running attack against this function could lead to unauthorized entities intercepting or duplicating the delegation of BTC, effectively siphoning off fees intended for the rightful transaction sender.


  function delegateBtc(bytes calldata btcTx, uint32 blockHeight, bytes32[] memory nodes, uint256 index, bytes memory script) external {
    require(script[0] == bytes1(uint8(0x04)) && script[5] == bytes1(uint8(0xb1)), "not a valid redeem script");

    bytes32 txid = btcTx.calculateTxId();
    require(ILightClient(LIGHT_CLIENT_ADDR).
      checkTxProof(txid, blockHeight, (btcConfirmBlock == 0 ? INIT_BTC_CONFIRM_BLOCK : btcConfirmBlock), nodes, index), "btc tx not confirmed");

    BtcReceipt storage br = btcReceiptMap[txid];
    require(br.value == 0, "btc tx confirmed");

    uint32 lockTime = parseLockTime(script);
    br.endRound = lockTime / ROUND_INTERVAL;
    require(br.endRound > roundTag + (minBtcLockRound == 0 ? INIT_MIN_BTC_LOCK_ROUND : minBtcLockRound), "insufficient lock round");

    (,,bytes29 voutView,)  = btcTx.extractTx();
    bytes29 payload;
    uint256 outputIndex;
    (br.value, payload, outputIndex) = voutView.parseToScriptValueAndData(script);
    require(br.value > (minBtcValue == 0 ? INIT_MIN_BTC_VALUE : minBtcValue), "staked value does not meet requirement");

    uint256 fee;
    (br.delegator, br.agent, fee) = parseAndCheckPayload(payload);
    if (!ICandidateHub(CANDIDATE_HUB_ADDR).isCandidateByOperate(br.agent)) {
      revert InactiveAgent(br.agent);
    }

    emit delegatedBtc(txid, br.agent, br.delegator, script, blockHeight, outputIndex);

    if (fee != 0) {
      br.fee = fee;
      br.feeReceiver = payable(msg.sender);
    }

    Agent storage a = agentsMap[br.agent];
    br.rewardIndex = a.rewardSet.length;
    addExpire(br);
    a.totalBtc += br.value;
  }
Proof of Concept
  1. Observation: An attacker continuously monitors the mempool for transactions calling the delegateBtc function.

  2. Construction: Upon identifying a legitimate transaction intended for delegation, the attacker constructs a similar transaction. This transaction duplicates the parameters of the original (btcTx, blockHeight, nodes, index, and script) but includes a higher gas price to ensure it is mined before the legitimate transaction.

  3. Execution: The attacker submits their transaction to the network. Given the higher gas price, miners prioritize this transaction over the original.

  4. Outcome: The attacker's transaction is processed first, potentially resulting in the redirection of fees or the invalidation of the legitimate user's transaction due to nonce or state conflicts.

BVSS
Recommendation

Ensure that the contract state checks the uniqueness of each identifier and rejects transactions with identifiers that have already been used.


Remediation Plan

SOLVED : The CoreDAO team solved the issue by adding the initial delegate BTC price.

Remediation Hash

6.2 Lack of Dynamic Governance Control Over CLAIM_ROUND_LIMIT in PledgeAgent Contract

// Informational

Description

The PledgeAgent contract, a component of our blockchain system designed for handling reward claims, employs a hardcoded constant, CLAIM_ROUND_LIMIT, to define the maximum number of rounds for which rewards can be claimed in a single transaction. This parameter plays a critical role in managing gas consumption during these transactions, ensuring that operations remain efficient and do not exceed gas limits. However, the current implementation's rigidity, resulting from the CLAIM_ROUND_LIMIT being a constant value, limits the system's adaptability to evolving network conditions or governance policies. As network congestion, gas prices, and operational parameters change, the inability to adjust this limit dynamically could lead to inefficiencies or hindered functionality for users attempting to claim rewards.


  uint32 public constant INIT_BTC_CONFIRM_BLOCK = 3;
  uint256 public constant INIT_MIN_BTC_LOCK_ROUND = 7;
  uint256 public constant ROUND_INTERVAL = 86400;
  uint256 public constant INIT_MIN_BTC_VALUE = 1e6;
  uint256 public constant INIT_BTC_FACTOR = 5e4;
  uint256 public constant BTC_STAKE_MAGIC = 0x5341542b;
  uint256 public constant CHAINID = 1116;
  uint256 public constant FEE_FACTOR = 1e18;
  int256 public constant CLAIM_ROUND_LIMIT = 500;
  uint256 public constant BTC_UNIT_CONVERSION = 1e10;
Score
Recommendation

Instead of a hardcoded constant, make CLAIM_ROUND_LIMIT a variable that can be adjusted through governance actions.


Remediation Plan

ACKNOWLEDGED : The CoreDAO team acknowledged the issue.

6.3 Missing Implementations in the IPledgeAgent Interface for BTC Delegation and Reward Distribution

// Informational

Description

The IPledgeAgent smart contract provides a framework for delegating Bitcoin (BTC) to the Core network, facilitating staking, reward claims, and the transfer of staked BTC among validators. The contract includes functions for parsing transaction data, validating Bitcoin transaction proofs, managing staking receipts, and distributing rewards. However, the IPledgeAgent interface does not reflect all the functionalities implemented in the contract, particularly the newer functions related to BTC delegation.


interface IPledgeAgent {
  function addRoundReward(address[] calldata agentList, uint256[] calldata rewardList) payable external;
  function getHybridScore(address[] calldata candidates, uint256[] calldata powers, uint256 round) external returns(uint256[] memory);
  function setNewRound(address[] calldata validatorList, uint256 round) external;
  function distributePowerReward(address candidate, address[] calldata miners) external;
  function onFelony(address agent) external;
}
Score
Recommendation

Consider implementing missing interface definitions.


Remediation Plan

SOLVED : The CoreDAO team solved the issue by adding missing interfaces.

Remediation Hash

6.4 Typo in BtcExpireInfo Struct Mapping Name

// Informational

Description

Within the PledgeAgent contract, specifically in the BtcExpireInfo struct, there is a typographical error in the naming of one of its mappings: agentExsitMap.

Score
Recommendation

Update all instances of agentExsitMap to agentExistMap within the contract.


Remediation Plan

SOLVED : The CoreDAO team solved the issue by fixing the typo.

Remediation Hash

6.5 Lack of Reentrancy Protection in Public Functions transferBtc and claimBtcReward

// Informational

Description

The transferBtc and claimBtcReward functions in the provided contract are public functions that involve the transfer of Ether (rewards) to external addresses. However, these functions do not implement any reentrancy protection mechanisms. In the case of transferBtc, the function calls collectBtcReward, which in turn calls distributeReward. The distributeReward function uses the low-level send function to transfer Ether (rewards) to the delegator's address. Although, the send / transfer function provides some protection against reentrancy by limiting the gas forwarded to the recipient's fallback function.

Score
Recommendation

Even if It does not pose risk directly, Consider implementing re-entrancy protection on the functions.


Remediation Plan

ACKNOWLEDGED : The CoreDAO team acknowledged the issue.

7. Automated Testing

Introduction

Halborn used automated testing techniques to enhance the coverage of certain areas of the smart contracts in scope. Among the tools used was Slither, a Solidity static analysis framework. After Halborn verified the smart contracts in the repository and was able to compile them correctly into their abis and binary format, Slither was run against the contracts. This tool can statically verify mathematical relationships between Solidity variables to detect invalid or inconsistent usage of the contracts' APIs across the entire code-base.

All issues identified by Slither were proved to be false positives or have been added to the issue list in this report.



Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.