Skip to content

Commit

Permalink
.lyx init
Browse files Browse the repository at this point in the history
  • Loading branch information
tantodefi committed Feb 1, 2024
1 parent 4cafb20 commit eafb605
Show file tree
Hide file tree
Showing 18 changed files with 2,254 additions and 164 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# .LYX Name Service

currently live on polygon: 0xf94279151ea5d9E89775b677481b1653D2f21927

collection on opensea: https://opensea.io/collection/lyx-name-service

live vercel link: https://dotlyx-k7b5eyiko-tantodefi.vercel.app/

# 🏗 Scaffold-ETH 2

<h4 align="center">
Expand Down
102 changes: 102 additions & 0 deletions packages/hardhat/contracts/Domains.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;

// We first import some OpenZeppelin Contracts.
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

import {StringUtils} from "./libraries/StringUtils.sol";
// We import another help function
import "@openzeppelin/contracts/utils/Base64.sol";

import "hardhat/console.sol";

// We inherit the contract we imported. This means we'll have access
// to the inherited contract's methods.
contract Domains is ERC721URIStorage {
// Magic given to us by OpenZeppelin to help us keep track of tokenIds.
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;

string public tld;

// We'll be storing our NFT images on chain as SVGs
string svgPartOne = '<svg xmlns="http://www.w3.org/2000/svg" width="270" height="270" fill="none"><path fill="url(#B)" d="M0 0h270v270H0z"/><defs><filter id="A" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="270" width="270"><feDropShadow dx="0" dy="1" stdDeviation="2" flood-opacity=".225" width="200%" height="200%"/></filter></defs><path d="M72.863 42.949c-.668-.387-1.426-.59-2.197-.59s-1.529.204-2.197.59l-10.081 6.032-6.85 3.934-10.081 6.032c-.668.387-1.426.59-2.197.59s-1.529-.204-2.197-.59l-8.013-4.721a4.52 4.52 0 0 1-1.589-1.616c-.384-.665-.594-1.418-.608-2.187v-9.31c-.013-.775.185-1.538.572-2.208a4.25 4.25 0 0 1 1.625-1.595l7.884-4.59c.668-.387 1.426-.59 2.197-.59s1.529.204 2.197.59l7.884 4.59a4.52 4.52 0 0 1 1.589 1.616c.384.665.594 1.418.608 2.187v6.032l6.85-4.065v-6.032c.013-.775-.185-1.538-.572-2.208a4.25 4.25 0 0 0-1.625-1.595L41.456 24.59c-.668-.387-1.426-.59-2.197-.59s-1.529.204-2.197.59l-14.864 8.655a4.25 4.25 0 0 0-1.625 1.595c-.387.67-.585 1.434-.572 2.208v17.441c-.013.775.185 1.538.572 2.208a4.25 4.25 0 0 0 1.625 1.595l14.864 8.655c.668.387 1.426.59 2.197.59s1.529-.204 2.197-.59l10.081-5.901 6.85-4.065 10.081-5.901c.668-.387 1.426-.59 2.197-.59s1.529.204 2.197.59l7.884 4.59a4.52 4.52 0 0 1 1.589 1.616c.384.665.594 1.418.608 2.187v9.311c.013.775-.185 1.538-.572 2.208a4.25 4.25 0 0 1-1.625 1.595l-7.884 4.721c-.668.387-1.426.59-2.197.59s-1.529-.204-2.197-.59l-7.884-4.59a4.52 4.52 0 0 1-1.589-1.616c-.385-.665-.594-1.418-.608-2.187v-6.032l-6.85 4.065v6.032c-.013.775.185 1.538.572 2.208a4.25 4.25 0 0 0 1.625 1.595l14.864 8.655c.668.387 1.426.59 2.197.59s1.529-.204 2.197-.59l14.864-8.655c.657-.394 1.204-.95 1.589-1.616s.594-1.418.609-2.187V55.538c.013-.775-.185-1.538-.572-2.208a4.25 4.25 0 0 0-1.625-1.595l-14.993-8.786z" fill="#fff"/><defs><linearGradient id="B" x1="0" y1="0" x2="270" y2="270" gradientUnits="userSpaceOnUse"><stop stop-color="#cb5eee"/><stop offset="1" stop-color="#FE005B" stop-opacity=".99"/></linearGradient></defs><text x="32.5" y="231" font-size="27" fill="#fff" filter="url(#A)" font-family="Plus Jakarta Sans,DejaVu Sans,Noto Color Emoji,Apple Color Emoji,sans-serif" font-weight="bold">';
string svgPartTwo = '</text></svg>';

mapping(string => address) public domains;
mapping(string => string) public records;

constructor(string memory _tld) payable ERC721(".lyx Name Service", ".LYX") {
tld = _tld;
console.log("%s name service deployed", _tld);
}

// This function will give us the price of a domain based on length
function price(string calldata name) public pure returns(uint) {
uint len = StringUtils.strlen(name);
require(len > 0);
if (len == 3) {
return 42 * 10**18; // 5 MATIC = 5 000 000 000 000 000 000 (18 decimals). We're going with 0.5 Matic cause the faucets don't give a lot
} else if (len == 4) {
return 4.2 * 10**18; // To charge smaller amounts, reduce the decimals. This is 0.3
} else {
return 4.2 * 10**18;
}
}

function register(string calldata name) public payable {
require(domains[name] == address(0));

uint256 _price = price(name);
require(msg.value >= _price, "Not enough Matic paid");

// Combine the name passed into the function with the TLD
string memory _name = string(abi.encodePacked(name, ".", tld));
// Create the SVG (image) for the NFT with the name
string memory finalSvg = string(abi.encodePacked(svgPartOne, _name, svgPartTwo));
uint256 newRecordId = _tokenIds.current();
uint256 length = StringUtils.strlen(name);
string memory strLen = Strings.toString(length);

console.log("Registering %s.%s on the contract with tokenID %d", name, tld, newRecordId);

// Create the JSON metadata of our NFT. We do this by combining strings and encoding as base64
string memory json = Base64.encode(
abi.encodePacked(
'{'
'"name": "', _name,'", '
'"description": "A domain on the .LYX name service", '
'"image": "data:image/svg+xml;base64,', Base64.encode(bytes(finalSvg)), '", '
'"length": "', strLen, '"'
'}'
)
);

string memory finalTokenUri = string( abi.encodePacked("data:application/json;base64,", json));

console.log("\n--------------------------------------------------------");
console.log("Final tokenURI", finalTokenUri);
console.log("--------------------------------------------------------\n");

_safeMint(msg.sender, newRecordId);
_setTokenURI(newRecordId, finalTokenUri);
domains[name] = msg.sender;

_tokenIds.increment();
}

function getAddress(string calldata name) public view returns (address) {
return domains[name];
}

function setRecord(string calldata name, string calldata record) public {
// Check that the owner is the transaction sender
require(domains[name] == msg.sender);
records[name] = record;
}

function getRecord(string calldata name) public view returns(string memory) {
return records[name];
}
}
87 changes: 0 additions & 87 deletions packages/hardhat/contracts/YourContract.sol

This file was deleted.

35 changes: 35 additions & 0 deletions packages/hardhat/contracts/libraries/StringUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
// Source:
// https://github.com/ensdomains/ens-contracts/blob/master/contracts/ethregistrar/StringUtils.sol
pragma solidity >=0.8.4;

library StringUtils {
/**
* @dev Returns the length of a given string
*
* @param s The string to measure the length of
* @return The length of the input string
*/
function strlen(string memory s) internal pure returns (uint) {
uint len;
uint i = 0;
uint bytelength = bytes(s).length;
for(len = 0; i < bytelength; len++) {
bytes1 b = bytes(s)[i];
if(b < 0x80) {
i += 1;
} else if (b < 0xE0) {
i += 2;
} else if (b < 0xF0) {
i += 3;
} else if (b < 0xF8) {
i += 4;
} else if (b < 0xFC) {
i += 5;
} else {
i += 6;
}
}
return len;
}
}
8 changes: 4 additions & 4 deletions packages/hardhat/deploy/00_deploy_your_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn
const { deployer } = await hre.getNamedAccounts();
const { deploy } = hre.deployments;

await deploy("YourContract", {
await deploy("Domains", {
from: deployer,
// Contract constructor arguments
args: [deployer],
Expand All @@ -33,12 +33,12 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn
});

// Get the deployed contract to interact with it after deploying.
const yourContract = await hre.ethers.getContract<Contract>("YourContract", deployer);
console.log("👋 Initial greeting:", await yourContract.greeting());
const yourContract = await hre.ethers.getContract<Contract>("Domains", deployer);
// console.log("👋 Initial greeting:", await yourContract.greeting());
};

export default deployYourContract;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags YourContract
deployYourContract.tags = ["YourContract"];
deployYourContract.tags = ["Domains"];
Loading

0 comments on commit eafb605

Please sign in to comment.