chiru-labs / ERC721A

https://ERC721A.org
MIT License
2.5k stars 839 forks source link

Need a way to dynamically set value for `_startTokenId` in constructor #471

Closed bagelface closed 1 year ago

bagelface commented 1 year ago

There's currently no way to set the value returned by _startTokenId dynamically via a constructor argument.

nidhhoggr commented 1 year ago

There's currently no way to set the value returned by _startTokenId dynamically via a constructor argument.

That's because it's extraneous and unnecessary since the the _startTokenId can be simply overridden to do the same.

bagelface commented 1 year ago

Not sure what you mean by that. There's no way to override it to return an immutable uint set by a constructor argument, because the ERC721A constructor uses it to set the value of _currentIndex and the value will always be uninitialized at that point.

fosgate29 commented 1 year ago

I agree with @nidhhoggr . You can simply overide _startTokenId

contract MyERC721A is ERC721A 
    function _startTokenId() internal view virtual override returns (uint256) {
        return 1000;  // 1000 as my startTokenId
    }
bagelface commented 1 year ago

I agree with @nidhhoggr . You can simply overide _startTokenId

contract MyERC721A is ERC721A 
    function _startTokenId() internal view virtual override returns (uint256) {
        return 1000;  // 1000 as my startTokenId
    }

Sorry you're completely missing the point. Here you're hard coding the value with a magic number. I'm currently working with ERC721A in the context of a LayerZero ecosystem. I need a way to easily dynamically set this value via the constructor, which is currently not possible.

nidhhoggr commented 1 year ago

Sorry you're completely missing the point. Here you're hard coding the value with a magic number. I'm currently working with ERC721A in the context of a LayerZero ecosystem. I need a way to easily dynamically set this value via the constructor, which is currently not possible.

If you absolutely need to pass a variable to a constructor to set the _startTokenId, you can create your own constructor to handle that. Check how the StartTokenIdHelper is used here: https://github.com/chiru-labs/ERC721A/blob/c66792253580acb2b7a873046858175d213e5b65/contracts/mocks/ERC721AStartTokenIdMock.sol#L15

Vectorized commented 1 year ago

The _startTokenId function is a view function. You can override it to return values from storage.

contract StartTokenIdHelper {
    uint256 private internal _startTokenIdValue;

    constructor(uint256 startTokenId_) {
        _initializeStartTokenId(startTokenId_);
    }

    function _initializeStartTokenId(uint256 value) private {
        _startTokenIdValue = value;
    }
}

contract ERC721AStartTokenIdMock is StartTokenIdHelper, ERC721AMock {
    constructor(
        string memory name_,
        string memory symbol_,
        uint256 startTokenId_
    ) StartTokenIdHelper(startTokenId_) ERC721AMock(name_, symbol_) {}

    function _startTokenId() internal view override returns (uint256) {
        return _startTokenIdValue;
    }
}