Blockful
Published in

Blockful

Referral Feature added to ENS

Earn commission by creating ENS DApps

Intro

The Ethereum Name Service wants to implement a referral program inside its ecosystem, so we did it! Every registration of a new ENS or the renewal of one creates a referrer opportunity. The referral commission is settled by the contract owner and the ‘_setBalance’ function will split the purchase rewarding the same percentage that was previously settled. To disable referral commission, simply change its value to 0 and no rewards will be given.

ENS registrations after referral feature

Implementation

For backward compatibility, we created ETHRegistrarControllerV2 and IETHRegistrarControllerV2 for adding this feature and the next ones we are working on.

No additional imports were needed. Currently using the IETHRegistrarControllerV2 interface.

Variables

referralFee: A variable with type uint256 called ‘referralFee’ should be initialized with any value from 0 to 1000 — for better granularity. Representing the percentage for which the referrer will receive.

uint256 public referralFee = 50;

balances: A mapping variable addressing the uint256 eth value into the referrer address. Storing the information within the contract that allows the referrer to claim that value by calling the ‘withdrawn’ function

mapping(address => uint256) public balances;

Functions

setReferralFee: A set function, for the ‘referralFee’ value, was made to adjust as intended by the protocol. Notice the event emission registering the change as well as the conditionals to assure that the minimum and maximum percentage are possible to be set correctly.

  • The function will accept one argument which will only be valid by being an int value between 0 and 1000, otherwise, it will revert.
  • Only the contract owner can call the function
setReferralFee function

_setBalance: This function is supposed to split the eth received after purchase or renewal of an ENS domain, based on the percentage settled in the referralFee variable. It has two inputs:

  • address referrer
  • uint256 amount

The referrer will have the amount stored in a map in case criteria are met, being eligible to withdraw that amount by calling the ‘withdraw’ function. Otherwise, in case there is no referrer set or the commissions are off, the entire amount will be registered in the name of the current contract owner.

_setBalance function

withdraw: A regular and safe approach to withdraw:

withdraw function

This will always, simply empty the user balance registry and transfer that amount back to him, the ‘msg.sender’.

Depending on how this function will be handled by the front-end or in case other contracts want to externally call it, we can save some future trouble on gas waste, by setting a ‘require’ function to avoid registering in the mapping and also trying to call a transaction evaluated in 0 eth.

Interface

Event Emission: The importance of event emission is due to the easy task which is collecting those data externally to generate useful statistics. For this reason, we tried to implement the emit event where the ‘NameRegistered’ and ‘NameRenewed’ are being implemented, facing an issue with the _register function, where it reached a stack-too-deep issue. Remaking the contract's internal architecture to better fit the referrer event within both records above would be the best approach.

Created events to handle referral business: Our turnaround was emitting the event inside the ‘_setBalance’ internal function, thus creating a separated event record named ‘ReferrerReceived’ and ‘ReferralFeeUpdated’, to track the referral usage, adding every successful referral program into the logs. ‘indexed’ is being used to search the logs easily

event structure

Changes

The changes that had to be made to the previous version to better fit the referral function.

Functions

register: This function is currently receiving the referrer address as an input from the back-end, being sent straight to the ‘_setBalance’ function after all the requirements have been met. Read concerns in conclusion, about a possible security breach and optimization. The function is called by passing two arguments:

  • address referrer
  • uint256 totalPrice
_setBalance(referrer, totalPrice);

renewal: The renewal function follows the same behavior as the register. It receives the referrer address, inputting the value on the front-end, and only is used when the function calls ‘_setBalance’ after all the requirements are met.

Interface

Moved events from ETHResitrarControllerV2.sol to IETHRegistrarControllerV2.sol: We realized that the standard for event management in the ENS contracts standard, is to have its initial structure settled inside the interface of the given contract that will emit the event. Although we have a different scenario in the ‘ETHRegistrarControllerV2’, where the structures were previously settled in the main contract, instead of where it is supposed to be, at ‘IETHRegistrarControllerV2’. Thus we moved the event structure.

Extra improvements

Rewriting some tests to TypeScript and adding typechain we found some errors and saw an opportunity for creating a npm package that we used in test improvements, if you are curious, here is the article about it.

BulkRenewal: We found that a test wasn't testing the renewAll function properly, discovering an error in the BulkRenewal.sol.

The error is at line 12, calling renew
The function that renewAll is calling

For renewing a name you should only pay price.base (line 15 from gist above). The renewAll function was calling renew with msg.value being price.base + price.premium, causing the error "Transaction reverted: function selector was not recognized and there’s no fallback nor receive function".

ETHRegisterController (V1): The withdraw test wasn't actually testing the withdraw functionality from the contract.

The state from the local blockchain is being reverted after each test because of these hooks above.

This means before the withdraw function is called, the contract already was with 0 ether, then the except assertion would pass even if the withdraw function wasn't executing as expected.

All corrections are at the Blockful repository

Conclusion

There is a huge opportunity for referrals in the ecosystem. User and protocol working together to boost the protocol functionalities providing more engagement and flourishing the partnership.

Follow us and learn more!

Blockful | 🐦 | 🐱‍👤

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store