Explore Phi

Create Philand

Making it even easier and more fun to use Ethereum.
The Ethereum Name Service (ENS) is a decentralized domain name system on the Ethereum. It allows users to create human-readable names for their Ethereum addresses, making it easier for others to find and interact with them.
For example, you could use an Ethereum address with the name "philand.eth". This would make it easier for others to find and use that address. ENS is a useful tool for making Ethereum addresses more user-friendly and accessible.
PHI is a service that extends the Ethereum Name Service by allowing users to create custom, visual representations of their Ethereum addresses. With PHI, you can enhance your Ethereum experience by personalizing your address with a unique, cute "land".
Our fully customizable lands make an extra layer of ENS, making it even easier and more fun to use Ethereum.
You can create your own ensLand.
On this page, we will discuss how we use the Ethereum Name Service (ENS) to create our "philand". We will also explain the benefits and potential of this approach.

We will explain how the system works.


At first, frontend checks the ENS subgraph (https://thegraph.com/hosted-service/subgraph/ensdomains/ens) to see which ens do user have.
Using graph and check users ens
In this case, user has "oyashirazu.eth". Next, frontend requests coupon to the backend.


Our Backend system checks ENS owner, and if there are no issues, ECDSA coupon is created by the admin private key. (admin key is saved at KMS)
const result = await ensGetOwner(provider, ensname);
// check request address is ensowner
if (result.toLowerCase() == address.toLowerCase()) {
// AWS KMS documentation (https://docs.aws.amazon.com/kms/)
const decrypted = await kms.decrypt(kmsparams).promise();
const secretkey = decrypted.Plaintext?.toString("base64");
const signerPvtKey = Buffer.from(secretkey!, "hex");
const hashBuffer = generateHashBuffer(
["string", "address", "address"],
[params.name, params.address, REGISTRY_CONTRACT_ADDRESS],
// use a private key stored in AWS KMS to create an ECDSA signature.
const coupon = createCoupon(hashBuffer, signerPvtKey);
const responseBody = JSON.stringify({ coupon: serializeCoupon(coupon) });
return successResponse(responseBody); //<- frontend get coupon
// ens owner check
async function ensGetOwner(provider: any, name: string) {
const ensAddr = (await provider.getNetwork()).ensAddress;
const ensAbi = ["function owner(bytes32) view returns (address)"];
const contract = new ethers.Contract(ensAddr, ensAbi, provider);
const addr = await contract.owner(ethers.utils.namehash(name));
if (addr === ethers.constants.AddressZero) {
return null;
return addr;
// create Coupon functions
function createCoupon(hash: any, signerPvtKey: any) {
return ecsign(hash, signerPvtKey);
function generateHashBuffer(typesArray: any, valueArray: any) {
return keccak256(toBuffer(ethers.utils.defaultAbiCoder.encode(typesArray, valueArray)));
function serializeCoupon(coupon: { r: any; s: any; v: any }) {
return {
r: bufferToHex(coupon.r),
s: bufferToHex(coupon.s),
v: coupon.v,
We are using ECDSA signatures for verification in our backend/contract.
For more information about ECDSA, please refer to the provided link.


Our frontend uses ECDSA coupons and call createPhiland method. Then, user creates a "Philand"
* @title createPhiland
* @notice Send create message to phimap
* @param name : ens name
* @dev include check ENS using coupon
function createPhiland(string memory name, Coupon memory coupon) external onlyENSOwner(name, coupon) {
if (ownerLists[map][name] != address(0)) {
revert AllreadyClaimedPhiland({ sender: msg.sender, owner: ownerLists[map][name], name: name });
unchecked {
ownerLists[map][name] = msg.sender;
// request the philand creation of a philand contract for name(msg.sender).
IPhiMap _phimap = IPhiMap(map);
_phimap.create(name, msg.sender);
emit LogCreatePhiland(msg.sender, name);
// modifier checks whether the msg.sender is the owner of a specific ensname.
modifier onlyENSOwner(string memory name, Coupon memory coupon) {
// Check that the coupon sent was signed by the admin signer
bytes32 digest = keccak256(abi.encode(name, msg.sender, address(this)));
if (!isVerifiedCoupon(digest, coupon)) {
require(isVerifiedCoupon(digest, coupon), "Invalid coupon");
function isVerifiedCoupon(bytes32 digest, Coupon memory coupon) internal view returns (bool) {
address signer = ecrecover(digest, coupon.v, coupon.r, coupon.s);
if (signer == address(0)) {
revert ECDSAInvalidSignature({ sender: msg.sender, signer: signer, digest: digest, coupon: coupon });
return signer == _adminSigner;
Once these verifications are successfully completed, you will be able to obtain your ENS philand.
Create you Philand

* CONTROLLER can create Philand but ...

When an ENS doamin is purchased at OpenSea(or other marketplace), only the REGISTRANT is transferred to your wallet and the CONTROLLER remains with the previous owner. (Because the REGISTRANT means the ownership of an ENS, the controller does not necessarily have to be the owner of that ENS.)


You can test philand visual experience using Playground. It is completely free and no restriction
Phi Land
Phi Land