https://github.com/la-bomba-studio/hesty-contract/tree/29596447b9a06d4ad53360d4a15f349ebf9fa0d8
Description:
The incorrect calculation in the getInvestmentTokens function of TokenFactory contract will cause a severe loss for investors, as users receive significantly fewer tokens than they should.
The initialSupply of property tokens is minted in multiples of 10 ** 18 (18 decimals):
// Property Token Supply Issuance
@> _mint(address(tokenManagerContract_), initialSupply_ * 1 ether);
But when users call getInvestmentTokens, their investment is not adjusted accordingly:
@> SafeERC20.safeTransfer(IERC20(p.asset), user, rightForTokens[user][id]);
As a result, users receive tokens equivalent to their invested amount without the necessary multiplication by 10 ** 18. This leads to users receiving a negligible amount of tokens, making it impossible to recover their investment.
Impact:
Mitigation:
Update the calculation in the getInvestmentTokens function of the TokenFactory contract by multiplying the token amount by 10 ** 18 (the decimals of the property token) to ensure correct token distribution.
-- SafeERC20.safeTransfer(IERC20(p.asset), user, rightForTokens[user][id]);
++ SafeERC20.safeTransfer(IERC20(p.asset), user, rightForTokens[user][id] * 1 ether);
Exploit Scenario:
buyTokens function of the TokenFactory contract.getInvestmentTokens function.2 * 10 ** 18), but instead, it only issues 2 wei (the smallest unit).Add this code in TokenFactory.test.js file:
describe("Incorrect Amount of Tokens Received", function () {
beforeEach(async function () {
//Not yet initialized so therefore address(0)
expect(await tokenFactory.referralSystemCtr()).to.equal("0x0000000000000000000000000000000000000000");
await tokenFactory.initialize(referral.address, issuance.address)
await hestyAccessControlCtr.connect(addr2).approveUserKYC(propertyManager.address);
await tokenFactory.addWhitelistedToken(token.address);
await tokenFactory.connect(propertyManager).createProperty(1000000, 1000, 4, 1, token.address, token.address, "token", "TKN", hestyAccessControlCtr.address)
expect(await tokenFactory.propertyCounter()).to.equal(1);
await tokenFactory.approveProperty(0, 2937487238472834);
// Approve owner kyc to allow him to buy property token
await hestyAccessControlCtr.connect(addr2).approveUserKYC(owner.address);
await token.approve(tokenFactory.address, 9);
await token.mint(owner.address, 8);
// User attempts to buy 2 Property Tokens
await tokenFactory.buyTokens(owner.address, 0, 2, addr3.address);
})
it("IncorrectTokens", async function () {
await ethers.provider.send("evm_mine", [2937487238472844]);
await tokenFactory.completeRaise(0);
await tokenFactory.getInvestmentTokens(owner.address, 0);
[PropertyToken, RevenueAddress] = await tokenFactory.getPropertyInfo(0);
// User only get 2 tokens instead of 2 x 10 ** 18 tokens
expect(await PropertyToken.balanceof(owner.address)).to.equal(2);
});
})