1

I have set up a dutch auction with the specifics mentioned here: What is expected in setting up the following dutch auction?

But it keeps reverting and doesn't seem to be returning the price which is the important part of the whole contract.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/[email protected]/token/ERC721/ERC721.sol";
import "@openzeppelin/[email protected]/access/Ownable.sol";
import "@openzeppelin/[email protected]/utils/Counters.sol";

contract MyToken is ERC721, Ownable {
    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdCounter;

    uint256 public immutable startPrice = 5 ether;
    uint256 public immutable startAt;
    uint256 public immutable endsAt;
    uint256 public immutable endPrice = 2 ether;
    uint256 public immutable discountRate = 0.01 ether;
    uint256 public duration = 300 hours;
    uint256 public immutable MAX_SUPPLY = 10000;

    constructor() ERC721("MyToken", "MTK") {
        startAt = block.timestamp;
        endsAt = block.timestamp + duration;
    }

    function price() public view returns (uint256) {
        if (endsAt < block.timestamp) {
            return endPrice;
        }
        uint256 timeElapsed = (block.timestamp - startAt);
        uint256 a = startPrice/(startAt - endsAt);
        return a * (timeElapsed - endsAt);
    }

    function safeMint(address to) public payable {
        require(msg.value >=price(), "Not enough ether sent");
        uint256 tokenId = _tokenIdCounter.current();
        require(tokenId < MAX_SUPPLY, "No more items left.");
        _tokenIdCounter.increment();
        _safeMint(to, tokenId + 1);
    }

    function withdraw() public onlyOwner {
        payable(owner()).transfer(address(this).balance);
    }

1 Answer 1

0

I believe the problem is here:

uint256 a = startPrice/(startAt - endsAt);

startAt - endsAt is a negative number. Try changing to the following:

uint256 a = startPrice/(endsAt - startAt);

If that doesn't work for you, convert the uint256 to int256. Here's a potential solution:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/[email protected]/token/ERC721/ERC721.sol";
import "@openzeppelin/[email protected]/access/Ownable.sol";
import "@openzeppelin/[email protected]/utils/Counters.sol";

contract MyToken is ERC721, Ownable {
    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdCounter;

    uint256 public immutable startPrice = 5 ether;
    uint256 public immutable startAt;
    uint256 public immutable endsAt;
    uint256 public immutable endPrice = 2 ether;
    uint256 public immutable discountRate = 0.01 ether;
    uint256 public duration = 300 hours;
    uint256 public immutable MAX_SUPPLY = 10000;

    constructor() ERC721("MyToken", "MTK") {
        startAt = block.timestamp;
        endsAt = block.timestamp + duration;
    }

    function price() public view returns (int256) {
        if (endsAt < block.timestamp) {
            return int256(endPrice);
        }
        uint256 timeElapsed = (block.timestamp - startAt);
        int256 a = int256(startPrice)/(int256(startAt) - int256(endsAt));
        return a * (int256(timeElapsed) - int256(endsAt));
    }

    function safeMint(address to) public payable {
        require(int256(msg.value) >= price(), "Not enough ether sent");
        uint256 tokenId = _tokenIdCounter.current();
        require(tokenId < MAX_SUPPLY, "No more items left.");
        _tokenIdCounter.increment();
        _safeMint(to, tokenId + 1);
    }

    function withdraw() public onlyOwner {
        payable(owner()).transfer(address(this).balance);
    }
}
4
  • That would change the logic of the price. a and b are numeric values. The price at time x will be a . x + b. In order to determine the values the equations: 0 = a . end_date b and start_price = a . start_date + b must be resolved. Is there a way to incorporate this into the code without changing the logic?
    – Mehsil sem
    Commented Jun 9, 2022 at 19:17
  • startAt - endsAt is always going to be negative in this context, so you can't use uint256. I edited my answer to include a conversion to int256 that no longer reverts, but the price is going to be returned as a negative.
    – Ammon
    Commented Jun 10, 2022 at 5:38
  • hey there was a slight mistake in the logic I wrote. I have edited it now. The return function is now a * (timeElapsed - endsAt) instead of addition. But when I try to apply it with the int256 as you have provided in this code, it again gets reverted. Anything I can change here to help with that?
    – Mehsil sem
    Commented Jun 10, 2022 at 16:32
  • Edited the code to include this change. In your snippet, timeElapsed and endTime are uint256 (unsigned integer -- can't be negative). Since endTime can be larger than timeElapsed, this would result in a negative number and reverts. Simply cast them to int instead of uint and it works great. Just know that you should make sure that it continues to do what you want during edge cases. i.e. check for overflow/underflow vulnerabilities.
    – Ammon
    Commented Jun 10, 2022 at 18:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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