Git Product home page Git Product logo

Comments (9)

atarpara avatar atarpara commented on June 15, 2024 1

@Vectorized In my dream i show ETH price is $4000.

from solady.

Vectorized avatar Vectorized commented on June 15, 2024 1

After more marinating, I think let's push this function further.

_mintAndSetExtraDataUnchecked.

Doesn't check if the token already exists. I assume you will use your own auto-incrementing counter.

We can keep the zero-address check and the account balance overflow check, as they are nearly free (no extra SLOADs). I know some codebases also abuse the zero-address check to validate inputs.

This feels like final form, the result of a million years of evolution, and I can feel the immense gas savings.

from solady.

Vectorized avatar Vectorized commented on June 15, 2024

Hmm... I didn't add it because it will make the code feel bloaty.

But i get the feeling of wanting to save that last 1k gas.

If this is to be implemented, it will only be for the _mint function.

If someone somehow needs _safeMint, I'm pretty sure they don't care about gas; so we can ignore the _safeMint variants.

from solady.

0xbid avatar 0xbid commented on June 15, 2024

Agree completely, most of the usefulness would come from extending just _mint.

from solady.

atarpara avatar atarpara commented on June 15, 2024

@Vectorized Solady ERC721 is designed such that minting, transferring, and burning don't affect the extra data. However, introducing this feature in Solady will result in a breaking change. One potential solution is to implement a new function called mintWithSetData. This function would essentially be a copy of the _mint function, but adding it would introduce duplicate code and increase the bytecode size.

from solady.

Vectorized avatar Vectorized commented on June 15, 2024

@atarpara Yes, it will require a separate function.

Internal functions are not added to the bytecode unless they are used.

Due to aesthetics, and to avoid touching an audited file, I may not actually include this function for the foreseeable future.

Right now, gas prices are still reasonable. May reserve this for a future date when ETH hits $3000+.

from solady.

0xbid avatar 0xbid commented on June 15, 2024

Is it really only 1k gas extra for calling _mint and then _setExtraData? My understanding of SSTORE is that the first use on the slot would be 20k, then the second one would be 5k, and if this were the case the savings would also be closer to 4k.

And this doesn't even take into the additional compute of having to re-calculate some steps to refer to the right slot, so maybe an additional 100 for that.

from solady.

0xbid avatar 0xbid commented on June 15, 2024

Right now, gas prices are still reasonable. May reserve this for a future date when ETH hits $3000+.

@Vectorized I'm down to just run make the modifications in my own copy of the lib, and be the first to experiment with the intended code. Would also validate via my own tests as well - that way you can have a high degree of confidence even before it gets to that point.

I think all that is needed is to combine these two functions:

    function _setExtraData(uint256 id, uint96 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let packed := sload(ownershipSlot)
            sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed)))))
        }
    }

    function _mint(address to, uint256 id) internal virtual {
        _beforeTokenTransfer(address(0), to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            to := shr(96, shl(96, to))
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Revert if the token already exists.
            if shl(96, ownershipPacked) {
                mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`.
                revert(0x1c, 0x04)
            }
            // Update with the owner.
            sstore(ownershipSlot, or(ownershipPacked, to))
            // Increment the balance of the owner.
            {
                mstore(0x00, to)
                let balanceSlot := keccak256(0x0c, 0x1c)
                let balanceSlotPacked := add(sload(balanceSlot), 1)
                if iszero(and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(balanceSlot, balanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)
        }
        _afterTokenTransfer(address(0), to, id);
    }

I'd give it a go but not as confident in my Yul skills 😄 - want to give it a shot?

from solady.

Vectorized avatar Vectorized commented on June 15, 2024

I really like this issue now, as it gave me a very good reason to include a internal mint function that skips the often extraneous token existence check.

from solady.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.