0

I writing a smart contract using Truffle and testing for that. I current meet this problem:

  • I send 0.5 ether to smart contract.
  • After that, contract get 0.0016 ether. (tested)
  • Then transfer again remaining ether for end user.
  • The gas estimate is about 199529.

I expect end user only loose 0.0016 ether (or little more, if we count gas price. But after testing, I see that user lost about 0.049 ether. I think this number is too much. Please explain for me this is normal behavior or there is some problems in my contracts.

Here is my code:

function _getPrice(
    uint8 _clazz,
    uint256 _quantity
)
internal
view
returns (uint256 _totalPrice, uint256 _priceIncrement, uint256 _currentPrice)
{
    _priceIncrement = priceIncrements[_clazz];
    _currentPrice = currentPrices[_clazz];
    _totalPrice = 0;
    uint256 totalAdoptedInClazz = totalAdoptedCreeptomas[_clazz];

    require(totalAdoptedInClazz.add(_quantity) <= MAXIMUM_ADOPTED_PER_CLASS);

    for (uint256 i = 0; i < _quantity; i++) {
        _totalPrice = _totalPrice.add(_currentPrice);
        totalAdoptedInClazz++;

        if (totalAdoptedInClazz == 100 ||
        totalAdoptedInClazz == 300 ||
        totalAdoptedInClazz == 600 ||
        totalAdoptedInClazz == 1000 ||
        totalAdoptedInClazz == 1500)
        {
            // half the increment price
            _priceIncrement >>= 1;
        }

        _currentPrice = _currentPrice.add(_priceIncrement);
    }
}

Here is method use above:

function _adopt(
    address _adopter,
    uint8 _clazz,
    uint256 _quantity,
    address _referrer
)
private
returns (uint256 _totalPrice)
{
    (_totalPrice, priceIncrements[_clazz], currentPrices[_clazz]) = _creeptomaPrice(_clazz, _quantity);

    userAdoptedCreeptomas[_adopter][_clazz] = userAdoptedCreeptomas[_adopter][_clazz].add(_quantity);
    totalAdoptedCreeptomas[_clazz] = totalAdoptedCreeptomas[_clazz].add(_quantity);

    emit AdoptedCreeptomasEvent(_adopter, _clazz, _quantity, _referrer);
}

And here is final method:

function adopt(
    uint256 _beastQuantity,
    uint256 _aquaticQuantity,
    uint256 _plantQuantity,
    address _referrer
)
public
payable
whenNotPaused
{
    require(_beastQuantity <= 3 && _aquaticQuantity <= 3 && _plantQuantity <= 3);

    address adopter = msg.sender;
    address actualReferrer = 0x0;

    // An adopter cannot be his/her own referrer.
    if (_referrer != adopter) {
        actualReferrer = _referrer;
    }

    // sending ether
    uint256 value = msg.value;

    uint256 price;

    // calculate price for buying beasts
    if (_beastQuantity > 0) {
        price = _adoptCreeptomas(
            adopter,
            CLASS_BEAST,
            _beastQuantity,
            actualReferrer
        );
        require(value >= price);
        value -= price;
    }


    // calculate price for buying aquatics
    if (_aquaticQuantity > 0) {
        price = _adoptCreeptomas(
            adopter,
            CLASS_AQUATIC,
            _aquaticQuantity,
            actualReferrer
        );
        require(value >= price);
        value -= price;
    }

    // calculate price for buying plants
    if (_plantQuantity > 0) {
        price = _adoptCreeptomas(
            adopter,
            CLASS_PLANT,
            _plantQuantity,
            actualReferrer
        );
        require(value >= price);
        value -= price;
    }

    // return remaining ether again for user
    msg.sender.transfer(value);

}

I try to call adopt(3, 3, 3, 0). It means maximum is 9 loops. but total gas is 200,000.

I used method estimateGas for testing:

    let est = await this.contract.adopt
        .estimateGas(beastQuantity, aquaticQuantity, plantQuantity, referer,
            {from: this.investor, value: ether(15)});
    console.log('est: ' + est);

Thanks

  • could you show your code? – Jaime May 4 '18 at 17:58
  • 200k gas is a lot, I suspect your code may be inefficient. – wtk219 May 4 '18 at 20:04
  • @Jaime I have updated my code. – hqt May 5 '18 at 17:18
  • I don't know which part is inefficient. Can you tell me how much gas often in normal contract. (without heavily calculating). – hqt May 5 '18 at 17:19
  • I see that operator like: totalAdoptedCreeptomas[_clazz] = totalAdoptedCreeptomas[_clazz].add(_quantity); costs about 16,000 gas. Is that so much ? I can have about maximum 6 operators like this. so maybe it is not efficient. – hqt May 5 '18 at 21:50

Your Answer

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

Browse other questions tagged or ask your own question.