Omniscia Alliance Block Audit
PaymentPortal Code Style Findings
PaymentPortal Code Style Findings
PPL-01C: Inexistent Visibility Specifiers
Type | Severity | Location |
---|---|---|
Code Style | Informational | PaymentPortal.sol:L12-L34 |
Description:
All contract-level variables do not have visibility specifiers explicitly set.
Example:
12uint256 subscriptionDuration = 3600 * 24 * 30; // in seconds13
14// All payments will be sent to this address15address paymentReceiverA;16address paymentReceiverB;17uint256 paymentShareA = 1000;18
19address albtToken;20address usdtToken;21
22address uniswapPair;23address uniswapRouter;24
25uint256 priceWithALBT;26uint256 priceWithUSDT;27
28uint256 maxSlippage = 990; // 1% (1000 = 100%)29
30// Whitelisted addresses31mapping(address => bool) whitelist;32
33// Stores the timestamp until which each address has access34mapping(address => uint256) access;
Recommendation:
We advise them to be set so to avoid discrepancies in the compilation outputs as currently the compiler assigns one automatically which may change between compiler versions.
Alleviation:
Visibility specifiers were introduced to all relevant variables.
PPL-02C: Inexplicable Value Literal
Type | Severity | Location |
---|---|---|
Code Style | Informational | PaymentPortal.sol:L68, L82, L86, L173, L188 |
Description:
The 1000
value literal is utilized to represent 100%, however, it is replicated across the codebase as a literal instead of being stored to a variable.
Example:
80function setPaymentShareA(uint256 _paymentShareA) public onlyOwner {81 require(82 _paymentShareA == 1000 || paymentReceiverB != address(0),83 'If payment is shared, payment receiver B must be set'84 );85
86 require(_paymentShareA <= 1000, 'Payment share must be between 0 and 1000');87
88 paymentShareA = _paymentShareA;89}
Recommendation:
We advise it to be stored to a contract-level constant
variable to alleviate any ambiguity and increase the legibility of the codebase. We should note that constant
variables behave exactly as literals as they are replaced during compilation, meaning that no gas cost alteration will be observed with this change.
Alleviation:
The value literal has now been replaced by a contract-level constant
labelled as HUNDRED_PERCENT
properly illustrating its purpose.
PPL-03C: Logical Block Optimization
Type | Severity | Location |
---|---|---|
Gas Optimization | Informational | PaymentPortal.sol:L191-L205 |
Description:
The conditional evaluating the _from
input argument being equal to address(this)
is performed twice redundantly.
Example:
191if (amountA > 0) {192 if (_from == address(this)) {193 SafeERC20.safeTransfer(IERC20(albtToken), paymentReceiverA, amountA);194 } else {195 SafeERC20.safeTransferFrom(IERC20(albtToken), _from, paymentReceiverA, amountA);196 }197}198
199if (amountB > 0) {200 if (_from == address(this)) {201 SafeERC20.safeTransfer(IERC20(albtToken), paymentReceiverB, amountB);202 } else {203 SafeERC20.safeTransferFrom(IERC20(albtToken), _from, paymentReceiverB, amountB);204 }205}
Recommendation:
We advise the amountA
and amountB
comparisons to instead be set within a single if-else
block that evaluates _from == address(this)
to optimize the gas cost of the function.
Alleviation:
The if
clauses were restructed to their more optimal implementation as per our recommendation.
PPL-04C: Non-Standard ERC20 Usage
Type | Severity | Location |
---|---|---|
Code Style | Informational | PaymentPortal.sol:L19, L20, L40, L41, L53, L158, L193, L195, L201, L203 |
Description:
The albtToken
is meant to represent the ALBT token and is utilized by being cast to the IERC20
interface and wrapped in a SafeERC20
direct library call.
Example:
192if (_from == address(this)) {193 SafeERC20.safeTransfer(IERC20(albtToken), paymentReceiverA, amountA);194} else {195 SafeERC20.safeTransferFrom(IERC20(albtToken), _from, paymentReceiverA, amountA);196}
Recommendation:
We advise the variable to instead be stored as an IERC20
directly and the SafeERC20
library to be used via its standardized method by introducing a using SafeERC20 for IERC20;
statement at the top of the contract block. The same can and should be applied for the usdtToken
member of the contract as well.
Alleviation:
The albtToken
is now properly stored as an IERC20
on which the SafeERC20
library is applied.
PPL-05C: Redundant Future Timestamp
Type | Severity | Location |
---|---|---|
Gas Optimization | Informational | PaymentPortal.sol:L176 |
Description:
The swapExactTokensForTokens
will successfully execute even with a timestamp argument of block.timestamp
as the comparison being done during the swap's expire
hook ensures that the timestamp is greater-than-or-equal-to (>=
) the current timestamp (block.timestamp
).
Example:
171uint256[] memory amounts = IUniswapV2Router01(uniswapRouter).swapExactTokensForTokens(172 priceWithUSDT,173 (albtAmount * (1000 - maxSlippage)) / 1000, // max % slippage174 route,175 address(this),176 block.timestamp + 3600 * 24177);
Recommendation:
We advise the addition and multiplications to be safely omitted from the codebase to reduce the gas cost of the call.
Alleviation:
The future timestamp has now been properly replaced by the current one.
PPL-06C: Superfluous Gas Cost
Type | Severity | Location |
---|---|---|
Gas Optimization | Informational | PaymentPortal.sol:L47, L48, L64-L74, L80-L89 |
Description:
The constructor
of the contract invokes the setPaymentReceivers
and setPaymentShareA
functions that in turn apply the onlyOwner
modifier redundantly.
Example:
36constructor(37 address _paymentReceiverA, // required38 address _paymentReceiverB, // optional, but _paymentShareA must be 100039 uint256 _paymentShareA, // what percentage of payments will go to payment receiver address A (1000 = 100%)40 address _albtToken, // address of the ALBT token41 address _usdtToken, // address of the USDT token42 address _uniswapPair, // address of the ALBT/USDT uniswap pair43 address _uniswapRouter, // address of the uniswap router44 uint256 _priceWithALBT, // price in USDT when paying with ALBT (USDT uses 6 decimals)45 uint256 _priceWithUSDT // price in USDT when paying with USDT (USDT uses 6 decimals)46) {47 setPaymentReceivers(_paymentReceiverA, _paymentReceiverB);48 setPaymentShareA(_paymentShareA);49
50 uniswapPair = _uniswapPair;51 uniswapRouter = _uniswapRouter;52
53 albtToken = _albtToken;54 usdtToken = _usdtToken;55
56 priceWithALBT = _priceWithALBT;57 priceWithUSDT = _priceWithUSDT;58}
Recommendation:
We advise the functions to be refactored to use an internal underscore-prefixed (_
) equivalent function that performs the statements instead, ensuring that the modifier is only applied to the external functions and not the internal ones thereby optimizing the gas cost of the contract's deployment.
Alleviation:
The code was refactored to contain underscore-prefixed counterparts of the functions that do not apply the modifier
redundantly and thus optimize the codebase.
PPL-07C: Variable Mutability Specifiers
Type | Severity | Location |
---|---|---|
Gas Optimization | Informational | PaymentPortal.sol:L19, L20, L22, L23, L50, L51, L53, L54 |
Description:
The linked variables are assigned to only once during the contract's constructor
.
Example:
36constructor(37 address _paymentReceiverA, // required38 address _paymentReceiverB, // optional, but _paymentShareA must be 100039 uint256 _paymentShareA, // what percentage of payments will go to payment receiver address A (1000 = 100%)40 address _albtToken, // address of the ALBT token41 address _usdtToken, // address of the USDT token42 address _uniswapPair, // address of the ALBT/USDT uniswap pair43 address _uniswapRouter, // address of the uniswap router44 uint256 _priceWithALBT, // price in USDT when paying with ALBT (USDT uses 6 decimals)45 uint256 _priceWithUSDT // price in USDT when paying with USDT (USDT uses 6 decimals)46) {47 setPaymentReceivers(_paymentReceiverA, _paymentReceiverB);48 setPaymentShareA(_paymentShareA);49
50 uniswapPair = _uniswapPair;51 uniswapRouter = _uniswapRouter;52
53 albtToken = _albtToken;54 usdtToken = _usdtToken;55
56 priceWithALBT = _priceWithALBT;57 priceWithUSDT = _priceWithUSDT;58}
Recommendation:
We advise them to be set as immutable
greatly optimizing the gas cost of the contract.
Alleviation:
The linked variables were all set to immutable
except for uniswapPair
which is no longer existent in the codebase.