The ATEN token contract follows the standard ERC-20 specification, including the use of 18 decimal places. The contract also includes an additional transferAndCall feature, which allows direct smart contract interactions without relying on the typical approve/transferFrom mechanism.
TransferAndCall
Besides the standard ERC20 token features (transfer(), balanceOf(), allowance(), etc), the following transferAndCall feature is also available:
import { ethers } from 'ethers';
// Placeholder values
const providerUrl = 'YOUR_RPC_PROVIDER_URL';
const privateKey = 'YOUR_PRIVATE_KEY';
const contractAddress = '0xYourContractAddress';
const recipientAddress = '0xRecipientAddress';
const transferAmount = ethers.BigNumber.from('1000000000000000000'); // 1 ETH
const stakeAmount = ethers.BigNumber.from('500000000000000000'); // 0.5 ETH
// Setup provider and wallet
const provider = new ethers.providers.JsonRpcProvider(providerUrl);
const wallet = new ethers.Wallet(privateKey, provider);
// ABI definitions
const transferAndCallAbi = [
"function transferAndCall(address to, uint256 amount, bytes calldata data) public returns (bool)"
];
const stakeAbi = [
"function stake(uint256 amount) public"
];
// Encode stake data
const stakeInterface = new ethers.utils.Interface(stakeAbi);
const stakeData = stakeInterface.encodeFunctionData('stake', [stakeAmount]);
// Encode transferAndCall data
const transferAndCallInterface = new ethers.utils.Interface(transferAndCallAbi);
const calldata = transferAndCallInterface.encodeFunctionData('transferAndCall', [recipientAddress, transferAmount, stakeData]);
// Create contract instance
const contract = new ethers.Contract(contractAddress, transferAndCallAbi, wallet);
async function sendTransaction() {
try {
const tx = await contract.transferAndCall(recipientAddress, transferAmount, stakeData);
const receipt = await tx.wait();
console.log("Transaction confirmed");
} catch (error) {
console.error('Transaction failed:', error);
}
}
// Send the transaction
sendTransaction();
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
interface ITokenCallReceiver {
function onTokenTransfer(
address from,
uint256 amount,
bytes calldata data
) external returns (bool);
}
contract TokenReceiver is ITokenCallReceiver {
// Define function selectors as constants
bytes4 private constant STAKE_SELECTOR = bytes4(keccak256("stake(uint256)"));
// Implement the onTokenTransfer function
function onTokenTransfer(
address from,
uint256 amount,
bytes calldata data
) external override returns (bool) {
// Extract the function selector
bytes4 selector;
assembly {
selector := calldataload(data.offset)
}
// Decode the function call data based on the selector
if (selector == STAKE_SELECTOR) {
// Extract the parameters for the stake function
(uint256 stakeAmount) = abi.decode(data[4:], (uint256)); // Skip the 4-byte function selector
// Handle the stake function logic
stake(stakeAmount);
} else {
revert("Unsupported function selector");
}
// Return success
return true;
}
// Example stake function that could be called
function stake(uint256 amount) public {
// Handle the staking logic here
}
}