Skip to content

Instantly share code, notes, and snippets.

@strollinghome
Last active May 26, 2023 11:08
Show Gist options
  • Select an option

  • Save strollinghome/b0259315651024f563b926d1940aba68 to your computer and use it in GitHub Desktop.

Select an option

Save strollinghome/b0259315651024f563b926d1940aba68 to your computer and use it in GitHub Desktop.
contract Renderer {
function updateDescription(
string memory description
) external override returns (bytes memory callback) {
editionMetadata[msg.sender].description = description;
bytes4 selector = IToken.batchMetadataUpdate.selector;
uint256 totalSupply = IToken(msg.sender).totalSupply();
assembly {
callback := mload(0x40)
mstore(callback, selector)
mstore(add(callback, 0x4), 0x1)
mstore(add(callback, 0x24), totalSupply)
return(callback, 0x44)
}
}
function updateMediaURIs(
string memory imageURI,
string memory animationURI
) external returns (bytes memory callback) {
editionMetadata[msg.sender].imageURI = imageURI;
editionMetadata[msg.sender].animationURI = animationURI;
bytes4 selector = IToken.batchMetadataUpdate.selector;
uint256 totalSupply = IToken(msg.sender).totalSupply();
assembly {
callback := mload(0x40)
mstore(callback, selector)
mstore(add(callback, 0x4), 0x1)
mstore(add(callback, 0x24), totalSupply)
return(callback, 0x44)
}
}
}
contract ERC721 {
bytes32 constant ERC4906_metadataUpdate_selector = (
0xc758f60000000000000000000000000000000000000000000000000000000000
);
bytes32 constant ERC4906_batchMetadataUpdate_selector = (
0x35ea9c4900000000000000000000000000000000000000000000000000000000
);
function _callMetaDataRenderer(
address _metadataRenderer,
bytes calldata data
) internal {
assembly {
if data.length {
let m := mload(0x40) // Grab the free memory pointer.
// Copy the calldata to the free memory.
calldatacopy(m, data.offset, data.length)
// Make the first call and revert if it fails.
if iszero(
call(
gas(), // Forward all gas.
_metadataRenderer, // The contract to call.
0, // Send 0 ETH.
m, // Start of input calldata.
data.length, // Length of input calldata.
0x00, // We'll use returndatasize instead.
0x00 // We'll use returndatasize instead.
)
) {
// Bubble up the revert if the call fails.
returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
// If there is return data, assume its a callback and execute.
if gt(returndatasize(), 0) {
// Copy the returndata to the free memory.
returndatacopy(m, 0x00, returndatasize())
// Reverts if selector is not a function we expect.
if iszero(
add(
eq(mload(m), ERC4906_metadataUpdate_selector),
eq(mload(m), ERC4906_batchMetadataUpdate_selector)
)
) {
revert(0x00, 0x00) // For better gas estimation.
}
if iszero(
call(
gas(), // Forward all gas.
address(), // `address(this)`.
0, // Send 0 ETH.
m, // Start of input calldata.
returndatasize(), // Length of returned callback.
0x00, // We don't need the returndata.
0x00 // We don't need the returndata.
)
) {
revert(0x00, 0x00) // For better gas estimation.
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment