1

Here ether scan links to failed transactions :

The contract call falls into gas error. It is basically chains of contracts making calls to one and another. As we have dig into the problem, we've seen that it fails on the method below.

Launchpad.sol go to contract

    /**
    * @dev Function to setup liquidity and transfer all amounts according to defined percents, if softcap not reached set Refunded flag.
    */
    function setupLiquidity() public onlyOwner {
        require(_isSoldOut == true || block.timestamp > _end , "LaunchpadToken: not sold out or time not elapsed yet" );
        require(_isRefunded == false, "Launchpad: refunded is activated");
        require(_isLiquiditySetup == false, "Setup has already been completed");
        _isLiquiditySetup = true;
        if(_raisedETH < _softCap){
            _isRefunded = true;
            return;
        }
        uint256 ethBalance = address(this).balance;
        require(ethBalance > 0, "LaunchpadToken: eth balance needs to be above zero" );
        uint256 liquidityAmount = ethBalance.mul(_liquidityPercent).div(_totalPercent);
        uint256 tokensAmount = _token.balanceOf(address(this));
        require(tokensAmount >= liquidityAmount.mul(_BASE_PRICE).div(_priceUniInv), "Launchpad: Not sufficient tokens amount");
        uint256 teamAmount = ethBalance.mul(_teamPercent).div(_totalPercent);
        uint256 layerFeeAmount = ethBalance.mul(_fee3).div(_totalPercent);
        uint256 supportFeeAmount = ethBalance.mul(_fee1).div(_totalPercent);
        uint256 stakeFeeAmount = ethBalance.mul(_fee1).div(_totalPercent);
        payable(_layerFeeAddress).transfer(layerFeeAmount);
        payable(_supportFeeAddress).transfer(supportFeeAmount);
        payable(_stakeFeeAddress).transfer(stakeFeeAmount);
        payable(_teamWallet).transfer(teamAmount);
        payable(_liquidityCreator).transfer(liquidityAmount);
        _token.safeTransfer(address(_liquidityCreator), liquidityAmount.mul(_BASE_PRICE).div(_priceUniInv));
    }

Somehow, it works on testnet; but fails on mainnet.

  • Testnet contract : link
  • Testnet success transaction with setupLiquidity() call. link

Theories are;

  • Chained contract calls have a higher gas limit requirement, the highest attempt so far is with 666,666 gas limit but it still fails. Maybe a number of investors caused this, as on testnet very few of them exist. If this is the case, how can we estimate the required gas limit?

  • Contract triggered transactions use 2300 gas, no matter how much gas limit initiator transaction has. That looks weird too.

Contracts :

1

The problem is that Launchpad transfers ethers to Layerx using .transfer, so the receiver has 2300 gas stipend

payable(_stakeFeeAddress).transfer(stakeFeeAmount);

Since Layerx fallback modifies storage it requires more than the 2300 and it cause out of gas error making setupLiquidity revert

function() external payable {
    ethToNextStake = ethToNextStake.add(msg.value); 
}
3
  • 1
    So, the transfer method always uses 2300 gas limit? How do you think it can be updated/fixed? If this is the case, no matter how much we increase the gas limit on our initiator tx, it will always use 2300 on contract call... Should we re-create the contract or what? Also why it did not create problem on testnet, shouldn't it create problem there also? – Kerem atam Dec 25 '20 at 20:44
  • 1
    @Kerematam The 2300 gas stipend applies when invoking the contract's fallback. Calling a payable function doesn't have such restriction, it will receive all gas available. In the linked ropsten transaction it worked because all calls were to EOA accounts (not contracts). – Ismael Dec 26 '20 at 2:00
  • Yeah, I see now. Thanks a lot. It seems like their money is locked into the contract. I don't see any way out. Because they hardcoded the addresses. – Kerem atam Dec 26 '20 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.