Payments on SKALE
Payments and tokenization is currently one of the most common usecases within the blockchain space. It’s important to recognize that with zero gas fees on SKALE, the way you handle payments and tokenization may require a small change compared to other networks.
Background
Section titled “Background”There are two types of tokens that are generally used for “payments” or “fungible value transfer” on most blockchains:
- Native Token: the native token of the blockchain (e.g. ETH on Ethereum, etc.)
- ERC-20 Tokens: tokens that are built on top of the blockchain (e.g. DAI, USDC, etc.)
When you’re building an application that faciliates payments on Ethereum and other chains that have gas fees, many developers utilize the native gas token as a primary form of payment. This is because the gas token is generally the most liquid asset and easiest to attain for users since they need it to execute transactions.
However, on SKALE, with zero gas fees or gasless transactions; you cannot use the native token as form of payment at all as it has 0 monetary value. Therefore, you should use other forms of value such as ERC-20 tokens or other tokens that have value on the network.
Technical Comparison
Section titled “Technical Comparison”Using Native Gas for Payments (BAD)
Section titled “Using Native Gas for Payments (BAD)”The following is how to transfer assets into a smart contract as a payment using the native gas token. In Solidity, this is msg.value. This should not be done on SKALE as the native token has no value.
/// SPDX-License-Identifier: MITpragma solidity ^0.8.9;
/// @title NativePayment/// @author TheGreatAxios/// @notice A simple contract that allows users to make payments with native ETH/// @dev This contract demonstrates handling of native ETH transferscontract NativePayment {
/// @notice Allows a user to make a purchase by sending ETH /// @dev Transfers the sent ETH amount to the contract's balance /// @dev Uses low-level call to transfer ETH value within the contract /// @dev Reverts if the internal transfer fails function purchase() external payable { (bool sent,) = payable(address(this)).call{value: msg.value}(""); require(sent, "Failed to send Ether"); }}
Using ERC-20 for Payments (GOOD)
Section titled “Using ERC-20 for Payments (GOOD)”The following is how to use an ERC-20 token for payments. This is the recommended way to handle payments on SKALE.
/// SPDX-License-Identifier: MITpragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title ERC20Payment/// @author TheGreatAxios/// @notice A simple contract that allows users to make payments with ERC20 tokens/// @dev This contract leverages OpenZeppelin's SafeERC20 library for secure token transferscontract ERC20Payment { using SafeERC20 for IERC20;
/// @notice The ERC20 token used for payments IERC20 public token;
/// @notice Initializes the contract with a specific ERC20 token /// @dev Sets the token that will be used for all payment operations /// @param _token The address of the ERC20 token contract constructor(address _token) { token = IERC20(_token); }
/// @notice Allows a user to make a purchase by sending 100 tokens /// @dev Transfers 100 tokens from the sender to this contract using safeTransferFrom /// @dev The amount is hardcoded to 100e18 (100 tokens with 18 decimals) function purchase() external { token.safeTransferFrom(msg.sender, address(this), 100e18); }}