Texan Endowment Token

CertiKFiles named in the report

CertiK reviewed TEXAN TOKEN (Texan Endowment Token) on 21 Dec 2022: 20 findings, 0 critical; 17 marked fixed, 3 open.

No open critical findings
Open the reportOpen TEXAN TOKEN’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings20

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High000
Medium102
Low2015
MediumToken DistributionOpen

The tokens are originally sent to the contract creator at mint. However the difference in the amount of tokens held by the Origin Address and the amount of tokens outside can cause issues with creating a new stake by calling the function `startStake`.

Low`g_stakedStars` can be updated once instead of twOpen

In the function `endStake()`, `g_stakedStars` needs to have the `stakeTotal` subtracted as it will be minted to the user. This can be done by subtracting `stakeTotal` instead of subtracting `interestAccrued` and then `stake._stakedPrinciple`. In addition, `g_stakedStars` can not be less than the interest or principle as it is the total sum of these variables for all stakes.

LowRedundant CheckOpen

In the function `scrapeStake()`, it is checked if `previousPossibleStars > currentInterest`. However, this is always true as the `previousPossibleStars` is always the principle plus the total amount of accrued interest possible for the stake up to the `endOfStakeDay`. Opposed to the `currentInterest`, which is the amount of accrued interest up to the current day, where the current day must be less than the `endOfStakeDay` because of a `require()` statement earlier in the function. --- In the function `endStake()`, there is the following check: ```solidity=368 if(g_stakedStars >= (stake._possibleStars)){ ``` However, `g_stakedStars` is always updated with `stake._possibleStars`, so that it will always be the sum off all staked possible stars. Thus the check will always pass. --- In the function `endStake()`, there is the following check: ```solidity=373 if(g_stakedPrincipleStars >= stake._stakedPrinciple){ ``` However, `g_stakedPrincipleStars` is always updated with `stake._stakedPrinciple`, so that it will always be the sum off all stakes principle stars. Thus the check will always pass. --- In the function `endStake()`, there is the following check: ```solidity=396 if(g_stakedPrincipleStars >= stake._stakedPrinciple){ ``` However, `g_stakedPrincipleStars` is always updated with the `stake._stakedPrinciple`, so that it will always be the sum off all stakes principle stars. Thus the check will always pass. --- In the function `endStake()`, there is the following check: ```solidity=403 if (stakeTotal != 0) { ``` However, this the `stakeTotal` is either the `principle + accruedInterest` or `principle - penalty`. The maximum `penalty` is only 50 percent of the `principle` and the `principle` is at least `10000` so that the `stakeTotal` can never be `0`. --- In the function `_calculatePenalty()`, there is the following check: ```solidity=760 if (totalStakeDays <= 0) { totalStakeDays = 1 * pctprecision; //sets minimum amt for calculation } ``` However, this is only called in `endStake()` so that the `totalStakeDays` must be at least `MIN_STAKE_DAYS * pctprecision`, thus it is always greater than `0`. --- In the function `_calculatePenalty()`, there is the following check: ```solidity=763 if (calcDays[0] < calcDays[1]) { // should never happen... condition handled in parent } else ``` However, this is only called in `endStake()` in the else block after the if block with the condition that `calcDays[0] < calcDays[1]`. Thus this will never be true. --- In the function `_calculatePenalty()`, there is the following check: ```solidity=784 if (penaltyAmount <= 0) { penaltyAmount = 0; } ``` However, `penaltyAmount` is a `uint256`, thus if it is less than or equal to `0`, then it is already `0` and does not need to be assigned. --- In the function `_calculatePenalty()`, there is the following check: ```solidity=788 if (penaltyAmount > stake._stakedPrinciple) { penaltyAmount = stake._stakedPrinciple; } ``` The `penaltyAmount` is calculated as `(stake._stakedPrinciple * pctleft) / 100`, however the `pctLeft` can only be in the range `[0,50]`. This ensures the maximum `penaltyAmount` is equal to `stake._stakedPrinciple` so that it is impossible for the `penaltyAmount` to be greater than `stake._stakedPrinciple`. --- In the function `calculateStakeTotal()`, there is the following check: ```solidity=824 if (penalty > stake._stakedPrinciple) { // this should never happen but if it does, then set to 50% of the principle appliedPrinciple = stake._stakedPrinciple / 2; } ``` However, the `penalty` amount is always at most 50 percent of the principle so that it can never be greater than `stake._stakedPrinciple`.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (6)

  • contracts/TEXAN.sol
  • contracts/ERC20.sol
  • contracts/IERC20.sol
  • contracts/Context.sol
  • contracts/StakableEndowmentToken.sol
  • contracts/IERC20Metadata.sol

Part of TEXAN TOKEN’s security record

TEXAN TOKEN
Audits1 audit by 1 firmLast audit Dec 2022, by CertiK.
Critical findingsNo open critical findingsIn 1 report.
Open TEXAN TOKEN’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us