GND

Smart Contract Audit Report

Audit Summary

GND is building two new platforms where users can stake tokens and earn rewards and a platform where users can mint new liquidity positions.

For this audit, we reviewed the project team's contracts at commit d1e7ef4fccb18c3f5750fc954c8fcc627d77fc03 on the team's GitHub repository.

Audit Findings

Low findings were identified and the team should consider resolving these issues. In addition, centralized aspects are present.
Date: March 22nd, 2023.
Updated: March 27th, 2023 to reflect changes made to the GND contract that resolves Finding #1.

Finding #1 - GND - High (Resolved)

Description: Any user can use the burn() function to burn another user's tokens at any time.
function burn(address _from, uint256 _amount) external {
	_burn(_from, _amount);
}
Risk/Impact: Any user's tokens can be burned by another user at any time.
Recommendation: The "from" parameter should be removed and replaced with msg.sender in the burn() function.
Resolution: The team has added a require statement to the burn() function to enforce that the caller must be the xGND address.

Finding #2 - LPStaking - Low

Description: The supplyRewards() function is redundant, as rewards are never transferred from the LPStaking contract but are instead minted from the GND contract.
function supplyRewards(uint256 _amount) external onlyOwner {
	totalGNDdistributed = totalGNDdistributed.add(_amount);
	GND.transferFrom(msg.sender, address(this), _amount);
}
Risk/Impact: Any GND tokens sent to the contract by the owner will be locked in the contract.
Recommendation: The team should remove the supplyRewards() function and totalGNDdistributed state variable from the contract.
Resolution: The team has not yet addressed this issue.

Finding #3 - gmUSD - Informational

Description: The following if-statement used in both the mint() and redeem() functions is redundant as onlyArbitragor is permanently set to true.
if (onlyArbitragor) {
Recommendation: The team should either add a function that toggles the onlyArbitragor boolean value or remove the if-statement from both functions to increase gas savings on each call.

Finding #4 - UniswapV3LP - Informational

Description: The below require statement in the slippagify() function contains a tautology as the first condition will always be true.
require(slippage >= 0 && slippage <= 1e5, "not in range");
Recommendation: The team could modify the require statement as follows for additional gas savings on each call:
require(slippage <= 1e5, "not in range");

Finding #5 - xGND - Informational

Description: The shortVestingPeriod and vestingPeriod state variables cannot be modified but are not declared constant.
Recommendation: The above state variables could be declared constant for additional gas savings on each reference.

Finding #6 - LPStaking - Informational

Description: The devaddr and xGNDdistributed state variables are not used in the contract.
Recommendation: The above state variables should either be removed to reduce contract size and deployment costs or utilized in a way that fits the project team's intended functionality.

Contracts Overview

GND Contract:
  • The total supply of the token is set to 18,000 $GND and is minted to the deployer upon deployment.
  • The xGND address can burn any user's tokens to reduce the total supply at any time.
  • Any user can burn their own tokens to reduce the total supply at any time.
  • The Staking contract or xGND contract can mint any number of tokens to any address at any time.
  • The owner can update the Staking address and xGND address at any time.
  • As the contract is implemented with Solidity v0.8.x, it is safe from any possible overflows/underflows.
  • The contract complies with the ERC-20 token standard.
LPToken Contract:
  • The total supply of the token is set to zero upon deployment.
  • The owner can burn any user's tokens to reduce the total supply at any time.
  • The owner can mint any number of tokens to any address at any time.
  • As the contract is implemented with Solidity v0.8.x, it is safe from any possible overflows/underflows.
  • The contract complies with the ERC-20 token standard.
xGND Contract:
  • The total supply of the token is set to 40,000 $xGND and is minted to the deployer upon deployment.
  • Any user can burn their own tokens to reduce the total supply at any time.
  • The owner can mint any number of tokens to any address at any time.
  • Any user can initiate a lock transaction by specifying a number of GND tokens that will be burned. In return, the user is minted xGND at a 1:1 ratio to the specified GND amount.
  • Any user can initiate a full vest transaction by specifying a number of xGND tokens that will be burned. An allocate vest transaction will be executed in the xGNDstaking contract for 50% of the specified amount.
  • Users can claim their full vest after the 200 day vesting period has passed.
  • Upon claiming, the vest is deallocated in the xGNDstaking contract and GND tokens are minted to the user at a 1:1 ratio to the xGND amount.
  • Any user can initiate a half vest transaction by specifying a number of xGND tokens that will be burned. An allocate vest transaction will be executed in the xGNDstaking contract for 25% of the specified amount.
  • Users can claim their half vest after the 20 day vesting period has passed.
  • Upon claiming, the vest is deallocated in the xGNDstaking contract and GND tokens are minted to the user for 50% of the xGND amount.
  • The owner can update the Div contract at any time.
  • The contract utilizes ReentrancyGuard to prevent reentrancy attacks in applicable functions.
  • As the contract is implemented with Solidity v0.8.x, it is safe from any possible overflows/underflows.
  • The contract complies with the ERC-20 token standard.
LPStaking Contract:
  • Any user can initiate a deposit into a staking pool by specifying the pool ID and a token amount that will be transferred to the contract.
  • Any pending GND and xGND rewards are calculated and minted to the user on deposits.
  • Users can specify a number of their deposited tokens to withdraw from the contract at any time.
  • Any pending GND and xGND rewards are calculated and minted to the user on withdrawals.
  • The stake pool address can initiate a vote transaction by specifying a user's address, pool ID, and the user's new total vote power value.
  • The number of allocation points assigned to the specified pool is either increased or decreased by the change in votes.
  • The stake pool address can redeem a vote by specifying a user's address and a pool ID.
  • The specified pool's allocation points are decreased by the user's vote value and the user's vote value is reset to zero.
  • The owner can add a new staking pool at any time by specifying the staking token and the allocation points assigned to the pool.
  • The owner can update the allocation points assigned to a pool to any value at any time.
  • The owner can enable/disable all withdrawals at any time.
  • The owner can specify an amount of GND tokens to send to the contract at any time.
  • The owner can set the GND and xGND rewards per second to any value up to 1 ether at any time.
  • The owner can update the stake pool address at any time.
  • The owner can update the xGND and GND addresses at any time.
  • The team must exercise caution when assigning the staking tokens to avoid using fee-on-transfer tokens.
  • The contract utilizes ReentrancyGuard to prevent reentrancy attacks in applicable functions.
  • As the contract is implemented with Solidity v0.8.x, it is safe from any possible overflows/underflows.
xGNDstaking Contract:
  • The contract's only staking pool will be created upon deployment using the xGND token address specified by the deployer.
  • Any user can initiate a deposit into the staking pool by specifying the pool ID and a token amount that will be transferred to the contract.
  • A 0.5% Deposit fee is charged on all deposits and is transferred to the owner.
  • Users can specify a number of their deposited tokens to withdraw from the contract at any time.
  • Any pending WETH rewards are calculated and transferred to the user on deposits and withdrawals.
  • The user's vote power value is updated on all deposits and withdrawals.
  • Any user that has staked tokens can trigger an emergency withdrawal from which will withdraw their staked tokens without calculating rewards.
  • A 30% penalty fee is charged on all emergency withdrawals and is sent to the owner.
  • The Allocator address can initiate an Allocate vest transaction for a user by specifying an number of xGND tokens that will be increased for their staked amount and vested amount.
  • A 0.5% fee is charged and is decreased from the provided amount.
  • The user's staked amount and vested amount are increased by the specified number of tokens.
  • The Allocator address can Deallocate a vest for a user by specifying a number of tokens that will be decreased from their staked amount and vested amount.
  • Any user that has any voting power for the xGND pool can initiate a vote for a specified pool ID in the LPStaking contract to increase its allocation points.
  • Any user that has voted can unvote which will reset the user's vote power and decrease the allocation points for the pool in the LPStaking contract.
  • The owner can enable/disable all withdrawals at any time.
  • The owner can specify an amount WETH to send to the contract at any time.
  • The owner can set the WETH per second to any value up to 1 ether at any time.
  • The owner can set the RP per second to any value at any time.
  • The owner can update the reward token at any time.
  • The owner can update the LPStake and Allocator addresses at any time.
  • The contract utilizes ReentrancyGuard to prevent reentrancy attacks in applicable functions.
  • As the contract is implemented with Solidity v0.8.x, it is safe from any possible overflows/underflows.
gmUSD Contract:
  • The total supply of the token is set to zero upon deployment.
  • Any user can initiate a Genesis mint transaction by specifying an amount of either gmdUSDC or gDAI to transfer to the contract.
  • The user must grant the contract a sufficient allowance in order for the transaction to successfully occur.
  • The user is minted gmUSD at a 1:1 ratio to the specified amount.
  • The current gmUSD total supply must not currently exceed 150,000 tokens at the time of the transaction.
  • The contract's current gmdUSDC balance must not exceed 100,000 and current gDAI balance must not exceed 50,000 at the time of the transaction.
  • The contract's Arbitragor address can initiate a mint transaction by specifying an amount of either gmdUSDC or gDAI to transfer to the contract.
  • The Arbitragor must grant the contract a sufficient allowance in order for the transaction to successfully occur.
  • The Arbitragor is minted gmUSD at a 1:1 ratio to the specified amount.
  • The contract's Arbitragor address can specify an amount of either gmdUSDC or gDAI to redeem from the contract.
  • The Arbitragor's gmUSD tokens are burned at a 1:1 ratio to the specified amount.
  • The owner can update the Arbitragor address at any time.
  • As the contract is implemented with Solidity v0.8.x, it is safe from any possible overflows/underflows.
  • The contract complies with the ERC-20 token standard.
UniswapV3LP Contract:
  • The owner can mint a new position by specifying two token addresses, a fee value, a recipient address, and minimum and desired amounts for each token.
  • The owner will also specify an LP token address and a slippage value.
  • The two specified tokens are transferred from the caller to the contract for the desired amounts.
  • The minimum amount values are modified based on the specified slippage value.
  • A mint transaction is performed in the nonfungiblePositionManager contract and a deposit is created on behalf of the owner. The nonfungiblePositionManager contract is not in scope for this audit so our team are unable to provide an assessment with regard to its security.
  • An amount of the specified LP token is minted to the caller based on the returned liquidity amount from the mint transaction.
  • The owner can collect the fees associated with provided liquidity by specifying an NFT ID that represents their position at any time.
  • The fee amounts are calculated in the nonfungiblePositionManager contract and are sent to the owner of the position.
  • Any user can decrease liquidity by specifying an NFT ID, an amount of liquidity to remove, and a slippage value.
  • Liquidity is decreased in the nonfungiblePositionManager contract and fees are automatically collected.
  • 99.7% of the calculated token amounts after decreasing liquidity are sent to the caller and the caller's LP tokens are burned for the specified liquidity amount.
  • The remaining 0.3% is sent to the owner of the position.
  • Any user can increase liquidity of a position by specifying the NFT ID, an amount for each token, and a slippage value.
  • The two specified tokens are transferred from the caller to the contract for the desired added amounts.
  • An increase-liquidity transaction is performed in the nonfungiblePositionManager contract.
  • An amount of the specified LP token is minted to the caller based on the returned liquidity amount from the increase-liquidity transaction.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control
  • The owner can burn any user's tokens at any time in the LPToken contract.
  • The xGND address set by the team can burn any user's tokens at any time in the GND contract.
  • The owner can disable withdrawals in the LPStaking and xGNDstaking contracts at any time.
WARNING
Compiler Issues N/A PASS
Delegate Call to Untrusted Contract N/A PASS
Dependence on Predictable Variables N/A PASS
Ether/Token Theft N/A PASS
Flash Loans N/A PASS
Front Running N/A PASS
Improper Events N/A PASS
Improper Authorization Scheme N/A PASS
Integer Over/Underflow N/A PASS
Logical Issues N/A PASS
Oracle Issues N/A PASS
Outdated Compiler Version N/A PASS
Race Conditions N/A PASS
Reentrancy N/A PASS
Signature Issues N/A PASS
Sybil Attack N/A PASS
Unbounded Loops N/A PASS
Unused Code N/A PASS
Overall Contract Safety   PASS

Contract Source Summary and Visualizations

Name

Address/Source Code

Visualized
(Hover-Zoom Recommended)

GND

GitHub

Inheritance Chart.  Function Graph.

LPToken

GitHub

Inheritance Chart.  Function Graph.

LPStaking

GitHub

Inheritance Chart.  Function Graph.

gmUSD

GitHub

Inheritance Chart.  Function Graph.

UniswapV3LP

GitHub

Inheritance Chart.  Function Graph.

xGND

GitHub

Inheritance Chart.  Function Graph.

xGNDstaking

GitHub

Inheritance Chart.  Function Graph.

About SourceHat

SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1800+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value!
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!

Contact us today to get a free quote for a smart contract audit of your project!

What is a SourceHat Audit?

Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.

How Do I Interpret the Findings?

Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:

  • High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
  • Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
  • Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
  • Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.