Skip to content

Instantly share code, notes, and snippets.

@z0r0z
Last active December 29, 2023 10:20
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save z0r0z/6ca37df326302b0ec8635b8796a4fdbb to your computer and use it in GitHub Desktop.
Save z0r0z/6ca37df326302b0ec8635b8796a4fdbb to your computer and use it in GitHub Desktop.
Bind your Soul to an NFT deed
// SPDX-License-Identifier: GPL-v3.0-or-later
pragma solidity >=0.8.0;
import 'https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol';
import 'https://github.com/kalidao/kali-contracts/blob/main/contracts/libraries/Base64.sol';
/// @notice Bind your Soul to an NFT Deed.
contract Soulbinder is ERC721("Soulbinder", "SOUL") {
/// -----------------------------------------------------------------------
/// Soul Logic
/// -----------------------------------------------------------------------
function bindSoul() public {
_mint(msg.sender, uint256(uint160(msg.sender)));
}
function unbindSoul(uint256 id) public {
require(ownerOf[id] == msg.sender, "NOT_SOUL_BINDER");
_burn(id);
}
/// -----------------------------------------------------------------------
/// Metadata Logic
/// -----------------------------------------------------------------------
function tokenURI(uint256 id) public view override returns (string memory) {
return _buildTokenURI(id);
}
function _buildTokenURI(uint256 id) internal view returns (string memory) {
address soul = address(uint160(id));
string memory metaSVG = string(
abi.encodePacked(
'<text dominant-baseline="middle" text-anchor="middle" fill="white" x="50%" y="90px">',
"0x",
_toString(soul),
"'s SOUL",
"</text>"
)
);
bytes memory svg = abi.encodePacked(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" preserveAspectRatio="xMidYMid meet" style="font:14px serif"><rect width="400" height="400" fill="black" />',
metaSVG,
"</svg>"
);
bytes memory image = abi.encodePacked(
"data:image/svg+xml;base64,",
Base64.encode(bytes(svg))
);
return string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(
bytes(
abi.encodePacked(
'{"name":"',
name,
'", "image":"',
image,
'", "description": "I, msg.sender, hereby relinquish my soul (my incorporeal essence) to the holder of this deed, to be collected after my death. I retain full possession of my soul as long as I am alive, no matter however so slightly. This deed does not affect any copyright, immaterial, or other earthly rights, recognized by human courts, before or after my death. I take no responsibility about whether my soul does or does not exist. I am not liable in the case there is nothing to collect. This deed shall be vanquished upon calling the unbindSoul() function."}'
)
)
)
)
);
}
function _toString(address x) internal pure returns (string memory) {
bytes memory s = new bytes(40);
for (uint i = 0; i < 20; i++) {
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i)))));
bytes1 hi = bytes1(uint8(b) / 16);
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
s[2*i] = char(hi);
s[2*i+1] = char(lo);
}
return string(s);
}
function char(bytes1 b) internal pure returns (bytes1 c) {
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
else return bytes1(uint8(b) + 0x57);
}
}
@CountZer0
Copy link

'name' doesn't exist.
ownerOf needs to use parenthesis instead of square brackets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment