Omniscia Alliance Block Audit

PaymentPortal Code Style Findings

PaymentPortal Code Style Findings

PPL-01C: Inexistent Visibility Specifiers

TypeSeverityLocation
Code StyleInformationalPaymentPortal.sol:L12-L34

Description:

All contract-level variables do not have visibility specifiers explicitly set.

Example:

contracts/PaymentPortal.sol
12uint256 subscriptionDuration = 3600 * 24 * 30; // in seconds
13
14// All payments will be sent to this address
15address 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 addresses
31mapping(address => bool) whitelist;
32
33// Stores the timestamp until which each address has access
34mapping(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

TypeSeverityLocation
Code StyleInformationalPaymentPortal.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:

contracts/PaymentPortal.sol
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

TypeSeverityLocation
Gas OptimizationInformationalPaymentPortal.sol:L191-L205

Description:

The conditional evaluating the _from input argument being equal to address(this) is performed twice redundantly.

Example:

contracts/PaymentPortal.sol
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

TypeSeverityLocation
Code StyleInformationalPaymentPortal.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:

contracts/PaymentPortal.sol
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

TypeSeverityLocation
Gas OptimizationInformationalPaymentPortal.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:

contracts/PaymentPortal.sol
171uint256[] memory amounts = IUniswapV2Router01(uniswapRouter).swapExactTokensForTokens(
172 priceWithUSDT,
173 (albtAmount * (1000 - maxSlippage)) / 1000, // max % slippage
174 route,
175 address(this),
176 block.timestamp + 3600 * 24
177);

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

TypeSeverityLocation
Gas OptimizationInformationalPaymentPortal.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:

contracts/PaymentPortal.sol
36constructor(
37 address _paymentReceiverA, // required
38 address _paymentReceiverB, // optional, but _paymentShareA must be 1000
39 uint256 _paymentShareA, // what percentage of payments will go to payment receiver address A (1000 = 100%)
40 address _albtToken, // address of the ALBT token
41 address _usdtToken, // address of the USDT token
42 address _uniswapPair, // address of the ALBT/USDT uniswap pair
43 address _uniswapRouter, // address of the uniswap router
44 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

TypeSeverityLocation
Gas OptimizationInformationalPaymentPortal.sol:L19, L20, L22, L23, L50, L51, L53, L54

Description:

The linked variables are assigned to only once during the contract's constructor.

Example:

contracts/PaymentPortal.sol
36constructor(
37 address _paymentReceiverA, // required
38 address _paymentReceiverB, // optional, but _paymentShareA must be 1000
39 uint256 _paymentShareA, // what percentage of payments will go to payment receiver address A (1000 = 100%)
40 address _albtToken, // address of the ALBT token
41 address _usdtToken, // address of the USDT token
42 address _uniswapPair, // address of the ALBT/USDT uniswap pair
43 address _uniswapRouter, // address of the uniswap router
44 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.