stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: medium
Invalid

`SDLPoolCCIPController.sol::recoverTokens` does not properly handle the recovering of token leading to loss of token

Summary

The SDLPoolCCIPController.sol::recoverTokens function does not correctly handle the retrieval of tokens for users that mistakenly send token to the SDLPoolCCIPController.sol contract which would inevitably cause loss of token in a scenario where more than one user mistakenly send token to the contract.

Vulnerability Details

The fact that the SDLPoolCCIPController.sol::recoverTokens function doesn't have any check in place to determine how much token was actually mistakenly sent by a user claiming to get a retrieval actually leads to a vulnerability where when there is more than one user that actually mistakenly send the same token to the contract, the first user to reach out to the team for token retrieval would get all of the token balance on the contract and not what they mistakenly sent leading to loss of token for the remaining users.

Impact

There would be loss of token to every user that mistakenly send the same type of token to the contract except for the first person that reach out to the project for retrieval

Note: SDLPoolCCIPController.sol is a base contract for both SDLPoolCCIPPrimaryController.sol and SDLPoolCCIPSecondaryController.sol so we would be using the SDLPoolCCIPPrimaryController.sol for our test case

Below is a step by step guide to test and confirm the vulnerability
Open the sdl-pool-ccip-primary-controller.test.ts file and paste the below code in the beforeEach block of the test code

// here each we are funding each user with the token they would mistakenly send to the controller contract
await linkToken.transfer(accounts[1], toEther(10));
await linkToken.transfer(accounts[2], toEther(10));
await linkToken.transfer(accounts[3], toEther(10));
// here each user is approving the controller address the token the balance they would mistakenly send to it
await linkToken.connect(signers[1]).approve(controller.address, 100);
await linkToken.connect(signers[2]).approve(controller.address, 100);
await linkToken.connect(signers[3]).approve(controller.address, 100);

Then paste the below test inside of the describe block of the test code

it("recoverTokens does not work properly in a scenario where more than one person mistakenly sends money to the contract", async () => {
// here each user mistakenly send money to the controller contract
await linkToken.connect(signers[1]).transfer(controller.address, toEther(10));
await linkToken.connect(signers[2]).transfer(controller.address, toEther(10));
await linkToken.connect(signers[3]).transfer(controller.address, toEther(10));
// here user 3 retrieved their token
await controller.recoverTokens([linkToken.address], accounts[3]);
// here we are asserting that the user gets all the balance of Link token the controller contract instead of what they mistakenly sent
assert.equal(fromEther(await linkToken.balanceOf(accounts[3])), 30);
});

Then run the below code in your terminal

yarn test --grep more than one person mistakenly sends money

On running the code above you should get the below output that shows that indeed the vulnerability was exploited

✔ recoverTokens does not work properly in a scenario where more than one person mistakenly sends money to the contract (61ms)
1 passing (5s)

Tools Used

Hardhat Test Suite

Recommendations

I know well enough it can really be some extra works to always check how much is mistakenly sent by any user who mistakenly send this contract some token but if the protocol would prefer to keep this functionality then they would really need to have some eventListener that would always listen to an event that is emitted whenever the SDLPoolCCIPController.sol receive token and the event details can be used to map the sent amount to each user that mistakenly send the token and then whenever a user wants to retrieve their token this mapping can be use to get the amount sent by them and send them back just that amount instead of all the balance of the contract on the mistakenly sent token.

Updates

Lead Judging Commences

0kage Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
engrpips Submitter
almost 2 years ago
0kage Lead Judge
almost 2 years ago
0kage Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.