Skip to content

Instantly share code, notes, and snippets.

@Hebilicious
Last active Feb 17, 2021
Embed
What would you like to do?
Smoke Finance

Heb SMOKE Contracts Express Review

Medium post and Tokenomics

Links to the deployed contracts

Note :

The 3 following contracts were created at the same time as the others:

According to the admins, those contracts were tests redeployments.

Review

UPDATE 2 : We have a website coming ! A more in depth audit will be live very soon.

UPDATE :

After reviewing more extensively, it turnes out that there's another interesting exploit :

The infamous syrup incident is back. Or moreso... It never left. As of right now, it is still present in the pancakeswap source code This project inherited from Pancake, and therefore the bug is still present. In the article you can find out more about how they "fixed" it. Basically they discountinued the SYRUP token.

The SAUCE token as of right now is meaningless, and it needs to stay that way.

    // Withdraw without caring about rewards. EMERGENCY ONLY.
    function emergencyWithdraw(uint256 _pid) public {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][msg.sender];
        pool.lpToken.safeTransfer(address(msg.sender), user.amount);
        emit EmergencyWithdraw(msg.sender, _pid, user.amount);
        user.amount = 0;
        user.rewardDebt = 0;
    }

TLDR : Looks Good To Me

After reviewing all the source files, the usual culprits (migrator, syrup exploits) that have been rugging people left and right are not present, which is really refreshing. Finally a new project that doesn't have the infamous migrator code !

The admins contacted me for an audit the day before the token launched, which is a good sign. I hope this kind of behavior becomes the norm for the future projects.

You'll find the details of the things that could be potential risks below.

Details

No Timelock

The PitMaster is owned by this address. A timelock is a piece of code that locks functionality on an application until a certain amount of time has passed. Most projects start without a Timelock, giving more control to the devs, which help ensuring a smooth launch. The admins of the project plan to implement a Timelock post launch, ASAP.

Bug in the presale contract

A small un-intended bug present in the presale contract could allow bad actors to bypass the limit by sending the purchased SMOKE to another wallet, then buying more 😅 The PreSale is over and that gave the admin a headache when they launched. Smart contract devs, watch out for this !

PreSale.sol

    receive() external payable {
        require(startPresale <= now, "Presale has not yet started");
        require(WHITELIST[msg.sender] || whiteListOver, "You are not whitelisted!");
        uint256 amount = msg.value / pricePresale * 100;
        require(amount <= token.balanceOf(address(this)), "Insufficient token balance in ICO");
        require((amount + token.balanceOf(address(msg.sender)) <= (maxPerWallet / pricePresale * 100) ), "Over Max Per Wallet");
        token.transfer(msg.sender, amount);
    }

PitMaster owner powers

With great power comes great responsibility. When the owner isn't a Timelock, the following functions can be called by this address This is common and not a risk IF the owner is trusted to be a good actor.

PitMaster.sol

    function updateMultiplier(uint256 multiplierNumber) public onlyOwner {
        BONUS_MULTIPLIER = multiplierNumber;
    }
    function updateSmokePerBlock(uint256 _smokePerBlock) public onlyOwner {
        smokePerBlock = _smokePerBlock;
    }


    // Add a new lp to the pool. Can only be called by the owner.
    // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.
    function add(uint256 _allocPoint, IBEP20 _lpToken, bool _withUpdate) public onlyOwner {
        if (_withUpdate) {
            massUpdatePools();
        }
        uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;
        totalAllocPoint = totalAllocPoint.add(_allocPoint);
        poolInfo.push(PoolInfo({
            lpToken: _lpToken,
            allocPoint: _allocPoint,
            lastRewardBlock: lastRewardBlock,
            accSmokePerShare: 0
        }));
        updateStakingPool();
    }

    // Update the given pool's SMOKE allocation point. Can only be called by the owner.
    function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
        if (_withUpdate) {
            massUpdatePools();
        }
        uint256 prevAllocPoint = poolInfo[_pid].allocPoint;
        poolInfo[_pid].allocPoint = _allocPoint;
        if (prevAllocPoint != _allocPoint) {
            totalAllocPoint = totalAllocPoint.sub(prevAllocPoint).add(_allocPoint);
            updateStakingPool();
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment