Friend.tech — Smart Contract Breakdown

Anak Mirasing
Valix Consulting
Published in
10 min readOct 5, 2023
Friend.tech Smart Contract Breakdown

Introduction

Hey there! Welcome to this article, where we’ll take a closer look at the inner workings of the Friend.tech smart contract. We won’t spend too much time introducing what Friend.tech is.

We’re here to breakdown exactly how the Friend.tech smart contract operates. If you’re curious about this exciting platform, you’re in the right place. Let’s get started!

Outline of this article

  • What is Friend.tech?
  • Friend.tech Smart Contract Breakdown
  • Conclusion

What is Friend.tech?

Friend.tech is changing the way we think about social networking. Instead of just connecting friends, it does something different. It turns your connections into something valuable called “Shares” or “Keys.” Imagine being able to invest in your friend’s social network or in a group of users to show trustworthiness. It’s a different kind of social app.

In this system, every user on X can becomes a social token. You can purchase these tokens, sell them for a profit, or keep them as their worth increases with the reputation of the users they represent.

But that’s not all—Shares provide access to special chat rooms for influencers, premium content, and more.

Friend.tech belongs to the Socialfi sector of blockchain applications, making it a truly unique and exciting addition to the decentralized world.

Massive hype on this contract (03/10/2023)

As of the day of writing this blog, the amount of ETH stored in the FriendtechSharesV1 contract stands at approximately 29,735 ETH, equivalent to around 49.3 million USD.

The number of transactions interacting with this contract has reached 9.5 million. This level of activity reflects substantial interest and engagement in the platform.

Now, let’s dive deeper into the Friend.tech smart contract.

Friend.tech Smart Contract Breakdown

In this section, let’s dive into the inner workings of the smart contract that powers Friend.tech.

The FriendtechSharesV1 contract is like a compact powerhouse, with only about 90 lines of code (excluding the Ownable contract). This small contract contains five crucial variables, one event, and ten functions. What’s even more impressive is that this concise codebase can handle substantial assets.

Below, we provide the FriendtechSharesV1 contract code for your examination. Looking into the code will provide you with a better understanding of how it enables the innovative features of the Friend.tech platform.

The FriendtechSharesV1 contract code

In the code snippet above, the FriendtechSharesV1 contract inherits from the Ownable contract, which is one of the popular libraries provided by OpenZeppelin. This inheritance equips the contract with functionality for ownership management, enabling the contract owner to execute specific privileged actions.

Furthermore, upon inspecting the code, it becomes evident that all variables and functions within the contract have their visibility set to “public”. This visibility setting allows both external and internal calls to access these variables and functions.

After inspecting the code above, let’s dive into more details about the key components of the FriendtechSharesV1 contract.

Variables

The crucial variables in the FriendtechSharesV1 contract

The FriendtechSharesV1 contract includes five variables (excluding the _owner variable inherited from the Ownable contract). Here is the list of variables:

protocolFeeDestination:
This address variable stores the destination address for receiving protocol fees.

protocolFeePercent:
This variable represents the percentage of protocol fees.

subjectFeePercent:
This variable represents the percentage of subject fees.

sharesBalance:
This mapping associates shares subjects (addresses) with their respective holders and their share balances.

sharesSupply:
This mapping tracks the supply of shares for each shares subject.

These variables, protocolFeeDestination, protocolFeePercent, subjectFeePercent, sharesBalance, and sharesSupply, have public visibility, making it easy to track or view their values externally.

Event

Trade event is triggered whenever shares are traded

The FriendtechSharesV1 contract provides a single event named Trade. This event is triggered whenever shares are traded using the buyShares and sellShares functions.

The Trade event logs various details about each trade, including:

  • The trader’s address
  • The subject’s address
  • The trade type (buy or sell)
  • The amounts of shares and ether involved
  • Details about protocol and subject fees
  • The share supply

Functions

The list of functions that can be accessed only by the contract owner.

In the code snippet above, we list the functions that are accessible exclusively to the contract owner. These functions grant the contract owner the ability to configure three crucial aspects related to the fees on this platform:

  • setFeeDestination:
    This function enables the contract owner to designate the destination address for receiving protocol fees
  • setProtocolFeePercent:
    This function grants the contract owner the authority to set the percentage of protocol fees
  • setSubjectFeePercent:
    This function provides the contract owner with the capability to establish the percentage of subject fees

🚨Remarkably, these three functions do not include input validation, maximum fee constraints, or time-lock mechanisms. Consequently, the contract owner has the freedom to set these values according to their preferences.

Next, the functions above work together to determine the prices at which shares can be bought and sold within the FriendtechSharesV1 contract.

  • getPrice:
    This is a pure function that calculates the price based on the supply and the amount of shares being bought or sold
  • getBuyPrice:
    This is a view function that retrieves the buy price of shares for a specific shares subject. It utilizes the getPrice function with the current supply and the desired amount of shares to be purchased
  • getSellPrice:
    This function is similar to the getBuyPrice function and is also a view function. It calculates the sell price of shares for a specific shares subject by using the getPrice function with the adjusted supply after selling the specified amount of shares

These functions work together to determine the prices at which shares can be bought and sold within the FriendtechSharesV1 contract.

The interesting function of this part is the getPrice function. This function determines share prices based on the current supply of shares and the number of shares being evaluated.

Let’s provide a specific example of how the getPrice function works with given values for supply and amount.

// Suppose we have the following values and calculate the price:
supply = 100
amount = 1

// sum1 is calculated for the initial supply of 100:
sum1 = (100 - 1) * 100 * (2 * (100 - 1) + 1) / 6 = 161,700

// sum2 is calculated when we consider an additional amount of 1 share:
sum2 = (100 - 1 + 1) * (100 + 1) * (2 * (100 - 1 + 1) + 1) / 6 = 161,701

// summation is the difference between sum2 and sum1:
summation = 161,701 - 161,700 = 1

// convert summation to wei using the factor 1 ether / 16000:
price = 1 * (1 ether / 16000) = 62,500,000,000,000,000 wei // 0.0625 ETH

So, with a supply of 100 and an additional amount of 1, the price of shares would be 62,500,000,000,000,000 wei or 0.0625 ETH.

Relationship between Price and Supply in Friend.tech

  1. Effect Of Buying (Increasing Supply):
    When the supply of shares (supply) increases, the price of each additional share (amount) also increases. This relationship is quadratic, meaning that as the supply grows, the price increase becomes steeper.
  2. Effect Of Selling (Decreasing Supply):
    If the supply decreases (for example, if shares are sold), the price of each additional share will decrease.
Relationship between Price and Supply

As in the relationship between price and supply above, the getPrice function explains how share prices shift when more people want to buy them or when more people want to sell them. When there's high demand with many buyers, prices rise, but they don't always rise at a consistent rate. Sometimes they go up quickly, and other times they rise more slowly. These price changes can cause shares to fluctuate in value, going both up and down.

Next, we have two convenient functions: getBuyPriceAfterFee and getSellPriceAfterFee. These functions are intended for external services or applications to calculate the buy and sell prices of shares after accounting for protocol and subject fees.

While they don't directly impact the contract's internal state, they provide valuable information for users or external services to understand the final prices they will pay or receive, considering all associated fees.

In the final section of the FriendtechSharesV1 contract, we encounter two crucial functions: buyShares and sellShares.

These functions are at the heart of the contract's functionality, allowing users to interact with shares on the platform by buying and selling them.

The buyShares function:

The buyShares function allows users to purchase shares from a specified shares subject by sending a certain amount of Ether as payment. This function calculates the price of the shares, which includes protocol and subject fees, and ensures that the sender provides enough Ether to complete the purchase. If the payment is sufficient, it updates the user's shares balance and the total supply of shares for the subject, logs the trade details, and transfers fees to the protocol and subject.

Let’s break it down line by line:

  1. Retrieve Supply:
    uint256 supply = sharesSupply[sharesSubject];
    This line retrieves the current supply of shares for the specified shares subject.
  2. Check Validity:
    require(supply > 0 || sharesSubject == msg.sender, "Only the shares' subject can buy the first share");
    This line checks whether the supply is greater than 0 or if the sender is the shares subject. If the supply is 0 (no shares exist) and the sender is not the shares subject, it prevents anyone except the subject from buying the first share.
  3. Calculate Price:
    uint256 price = getPrice(supply, amount);
    This line calculates the price of the shares based on the current supply and the desired amount of shares to purchase using the getPrice function.
  4. Calculate Protocol Fee:
    uint256 protocolFee = price * protocolFeePercent / 1 ether;
    Here, it calculates the protocol fee based on the price and the protocol fee percentage.
  5. Calculate Subject Fee:
    uint256 subjectFee = price * subjectFeePercent / 1 ether;
    This line calculates the subject fee based on the price and the subject fee percentage.
  6. Check Payment:
    require(msg.value >= price + protocolFee + subjectFee, "Insufficient payment");
    This checks if the Ether sent by the sender (msg.value) is greater than or equal to the total price, including protocol and subject fees. If the payment is insufficient, the function will not proceed.
  7. Update User Balance:
    sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] + amount;
    It updates the user's balance of shares within the specified shares subject.
  8. Update Supply:
    sharesSupply[sharesSubject] = supply + amount;
    This line increases the total supply of shares for the shares subject by the purchased amount.
  9. Emit Trade Event:
    emit Trade(msg.sender, sharesSubject, true, amount, price, protocolFee, subjectFee, supply + amount);
    It emits a trade event with details about the transaction, including the sender, shares subject, trade type (buy), the amount purchased, price, fees, and summation of supply.
  10. Transfer Funds:
    (bool success1, ) = protocolFeeDestination.call{value: protocolFee}("");
    This line attempts to transfer the protocol fee to the designated fee destination address.
  11. Transfer Funds:
    (bool success2, ) = sharesSubject.call{value: subjectFee}("");
    Here, it attempts to transfer the subject fee to the shares subject's address.
  12. Final Check:
    require(success1 && success2, "Unable to send funds");
    This final line checks whether both fee transfers were successful. If any of them fails, it raises an error.

🚨Remarkably for buyShares function from the check payment state:

require(msg.value >= price + protocolFee + subjectFee, "Insufficient payment");

If the buyer sends more Ether (msg.value)than the total cost of the transaction (i.e., price + protocolFee + subjectFee), the contract does not include a mechanism to refund the excess Ether back to the buyer.

The sellShares function:

The sellShares function enables users to sell their shares back to the contract. This function is essential for liquidity on the platform, allowing users to exit their share positions when desired. It involves several steps, including checking eligibility, calculating prices, handling fees, and updating balances.

Let’s break it down line by line:

  1. Retrieve Supply:
    uint256 supply = sharesSupply[sharesSubject];
    This line retrieves the current supply of shares for the specified shares subject.
  2. Check Validity:
    require(supply > amount, “Cannot sell the last share”);
    This line ensures that the user cannot sell more shares than what is available in the supply. If the supply is less than or equal to the amount, the transaction is halted with the specified error message.
  3. Calculate Price:
    uint256 price = getPrice(supply — amount, amount);
    The price of the shares to be sold is calculated using the getPrice function. It considers the adjusted supply after selling the specified amount of shares.
  4. Calculate Fees:
    uint256 protocolFee = price * protocolFeePercent / 1 ether;
    uint256 subjectFee = price * subjectFeePercent / 1 ether;
    These lines calculate the protocol and subject fees based on the price of the shares to be sold.
  5. Check Share Balance:
    require(sharesBalance[sharesSubject][msg.sender] >= amount, “Insufficient shares”);
    This line verifies that the user has a sufficient balance of shares to sell. If the user’s balance is less than the amount they intend to sell, the transaction will be reversed.
  6. Update User Balance:
    sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] — amount;
    The function deducts the sold shares from the user’s balance.
  7. Update Supply:
    sharesSupply[sharesSubject] = supply — amount;
    The total supply of shares for the shares subject is updated by reducing the sold amount.
  8. Emit Trade Event:
    emit Trade(msg.sender, sharesSubject, false, amount, price, protocolFee, subjectFee, supply — amount);
    It emits an event with details of the trade, including the seller, shares subject, trade type (sell), the amount sold, price, fees, and supply.
  9. Transfer Funds:
    (bool success1, ) = msg.sender.call{value: price — protocolFee — subjectFee}(“”);
    (bool success2, ) = protocolFeeDestination.call{value: protocolFee}(“”);
    (bool success3, ) = sharesSubject.call{value: subjectFee}(“”);
    These lines attempt to transfer the proceeds to the seller, protocol fees to the protocol fee destination, and subject fees to the subject’s address.
  10. Final Check:
    require(success1 && success2 && success3, “Unable to send funds”);
    This line ensures that all fund transfers were successful. If any of them fail, the transaction is halted, preventing funds from being lost.

Conclusion

In this article, we’ve broken down the FriendtechSharesV1 smart contract, uncovering the mechanism behind this innovative platform. We’ve explored the code, examined its functions, and explained how it facilitates transactions within Friend.tech’s unique ecosystem.

But our journey doesn’t end here. If you’re interested in more insights into the world of decentralized applications and smart contracts, stay tuned for our next article. Until then, enjoy your reading and happy learning!

Author Details

Anak Mirasing, Lead Blockchain Security Auditor and Consultant

About Valix Consulting

Valix Consulting is a blockchain and smart contract security firm offering a wide range of cybersecurity consulting services. Our specialists, combined with technical expertise, industry knowledge, and support staff, strive to deliver consistently superior quality services.

For any business inquiries, please contact us via Twitter, Facebook, or info@valix.io.

Resources

  • Friend.tech : Link
  • Friend.tech explained : Link
  • Smart Contract code on Base chain : Link

--

--