hats-finance / Accumulated-finance-0x75278bcc0fa7c9e3af98654bce195eaf3bb6a784

0 stars 0 forks source link

Failure of `delegate()` function due to missing `payable` #5

Open hats-bug-reporter[bot] opened 1 week ago

hats-bug-reporter[bot] commented 1 week ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0xcfbb1f68acaf08db07deb2d507a8e199c56d52b0a3fa4c3c03ed9efab16c1ef4 Severity: medium

Description: Description\ stROSEMinter.sol has delegate() function which can be accessed by contract owner to delegate the ROSE to staking address.

    function delegate(StakingAddress to, uint128 amount) public onlyOwner returns (uint64) {
        require(amount < type(uint128).max, ">MaxUint128");
        require(amount > 0, "ZeroDelegate");
        uint64 receiptId = nextReceiptId++;
        Subcall.consensusDelegate(to, amount, receiptId);
        delegationReceipts[receiptId] = DelegationReceipt({
            exists: true,
            to: to,
            blockNumber: block.number,
            receiptTaken: false,
            receiptTakenBlockNumber: 0,
            shares: 0,
            amount: amount
        });
        emit Delegate(to, amount, receiptId);
        return receiptId;
    }

delegate() would increase delegation by sending an amount of ROSE to the contract address. As per OASIS documentation,

The minimum amount of tokens one can delegate. The value is set to 100,000,000,000 base units, or 100 ROSE tokens.

A minimum 100 ROSE tokens would be able to delegate to staking address. The issue is that, the native ROSE token which is OASIS chains native token can be sent during delegate() function call as delegate() is not payable. To send ROSE tokens to contract in order to succesful delegate, delegate() should be payable.

Impact\ This breaks contracts core functionality due to failure of sending native ROSE to contract inorder to further delegate to recipient address.

Recommendations\ Consider delegate() to be payable.

-    function delegate(StakingAddress to, uint128 amount) public onlyOwner returns (uint64) {
+    function delegate(StakingAddress to, uint128 amount) public payable onlyOwner returns (uint64) {
-       require(amount < type(uint128).max, ">MaxUint128");
+      require(msg.value > 0 && msg.value < type(uint128).max, ">MaxUint128");
-       require(amount > 0, "ZeroDelegate");
+      uint128 amount = uint128(msg.value);
        uint64 receiptId = nextReceiptId++;
        Subcall.consensusDelegate(to, amount, receiptId);
        delegationReceipts[receiptId] = DelegationReceipt({
            exists: true,
            to: to,
            blockNumber: block.number,
            receiptTaken: false,
            receiptTakenBlockNumber: 0,
            shares: 0,
            amount: amount
        });
        emit Delegate(to, amount, receiptId);
        return receiptId;
    }
0xRizwan commented 1 week ago

Bit correction:

-    function delegate(StakingAddress to, uint128 amount) public onlyOwner returns (uint64) {
+    function delegate(StakingAddress to) public payable onlyOwner returns (uint64) {
-       require(amount < type(uint128).max, ">MaxUint128");
+      require(msg.value > 0 && msg.value < type(uint128).max, ">MaxUint128");
-       require(amount > 0, "ZeroDelegate");
+      uint128 amount = uint128(msg.value);
        uint64 receiptId = nextReceiptId++;
        Subcall.consensusDelegate(to, amount, receiptId);
        delegationReceipts[receiptId] = DelegationReceipt({
            exists: true,
            to: to,
            blockNumber: block.number,
            receiptTaken: false,
            receiptTakenBlockNumber: 0,
            shares: 0,
            amount: amount
        });
        emit Delegate(to, amount, receiptId);
        return receiptId;
    }
ilzheev commented 1 week ago

delegate(StakingAddress to, uint128 amount) delegates the amount from minter contract to the StakingAddress. No new tokens should be added via delegate – they can be added via deposit or direct transfer to the contract.