文件 1 的 10:Context.sol
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 2 的 10:IERC165.sol
pragma solidity ^0.7.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 3 的 10:IERC20.sol
pragma solidity ^0.7.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function burn(uint256 burnQuantity) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 10:IERC721.sol
import "./ERC165/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
文件 5 的 10:IERC721Enumerable.sol
import "./IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 6 的 10:IFaces.sol
import "./IERC721Enumerable.sol";
interface IFaces is IERC721Enumerable {
function mintedTimestampByIndex(uint256 index) external view returns (uint256);
function segmentsUnlockedByIndex(uint256 index) external view returns (uint256);
function tokenNameByIndex(uint256 index) external view returns (string memory);
function isNameReserved(string memory nameString) external view returns (bool);
}
文件 7 的 10:ISFT.sol
import "./IERC20.sol";
interface ISFT is IERC20 {
function totalAccumulatedSupply() external view returns (uint256);
function accumulated(uint256 tokenIndex) external view returns (uint256);
function totalAccumulated(uint256 tokenIndex) external view returns (uint256);
function totalClaimed(uint256 tokenIndex) external view returns (uint256);
}
文件 8 的 10:Ownable.sol
pragma solidity ^0.7.0;
import "./Context.sol";
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 9 的 10:SFT.sol
pragma solidity ^0.7.0;
import "./ERC165/IERC165.sol";
import "./utils/SafeMath.sol";
import "./IERC20.sol";
import "./ISFT.sol";
import "./IFaces.sol";
import "./utils/Context.sol";
import "./utils/Ownable.sol";
contract SFT is Context, Ownable, ISFT {
using SafeMath for uint256;
uint256 public constant SECONDS_IN_A_DAY = 86400;
uint256 public constant SECONDS_IN_A_YEAR = SECONDS_IN_A_DAY * 365;
uint256 public constant INITIAL_ALLOTMENT = 500 * (10 ** 18);
uint256 public constant EMISSION_START = 1617667200;
uint256 public constant EMISSION_END = EMISSION_START + (SECONDS_IN_A_YEAR * 10);
uint256 public constant EMISSION_PER_DAY_YEAR_0 = 5.00 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_1 = 3.75 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_2 = 2.81 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_3 = 2.11 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_4 = 1.58 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_5 = 1.19 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_6 = 0.89 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_7 = 0.67 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_8 = 0.50 * (10 ** 18);
uint256 public constant EMISSION_PER_DAY_YEAR_9 = 0.36 * (10 ** 18);
uint256[10] public EMISSION_PER_DAY_YEARS = [ EMISSION_PER_DAY_YEAR_0,
EMISSION_PER_DAY_YEAR_1,
EMISSION_PER_DAY_YEAR_2,
EMISSION_PER_DAY_YEAR_3,
EMISSION_PER_DAY_YEAR_4,
EMISSION_PER_DAY_YEAR_5,
EMISSION_PER_DAY_YEAR_6,
EMISSION_PER_DAY_YEAR_7,
EMISSION_PER_DAY_YEAR_8,
EMISSION_PER_DAY_YEAR_9];
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
mapping(uint256 => uint256) private _lastClaim;
mapping(uint256 => uint256) private _claimedAmount;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
address private _facesAddress;
address private _addonsAddress;
constructor () {
_name = "SatoshiFinanceToken";
_symbol = "SFT";
_decimals = 18;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function lastClaim(uint256 tokenIndex) public view returns (uint256) {
require(IFaces(_facesAddress).ownerOf(tokenIndex) != address(0), "Owner cannot be 0 address");
require(tokenIndex < IFaces(_facesAddress).totalSupply(), "NFT at index has not been minted yet");
uint256 lastClaimed = uint256(_lastClaim[tokenIndex]) != 0 ? uint256(_lastClaim[tokenIndex]) : EMISSION_START;
return lastClaimed;
}
function totalAccumulatedSupply() public view override returns (uint256) {
require(block.timestamp > EMISSION_START, "Emission has not started yet");
require(IFaces(_facesAddress).ownerOf(0) != address(0), "Owner of NFT #0 cannot be 0 address");
require(0 < IFaces(_facesAddress).totalSupply(), "No NFTs have been minted yet");
uint256 nftSupply = IFaces(_facesAddress).totalSupply();
return nftSupply.mul(totalAccumulated(0));
}
function accumulated(uint256 tokenIndex) public view override returns (uint256) {
require(block.timestamp > EMISSION_START, "Emission has not started yet");
require(IFaces(_facesAddress).ownerOf(tokenIndex) != address(0), "Owner cannot be 0 address");
require(tokenIndex < IFaces(_facesAddress).totalSupply(), "NFT at index has not been minted yet");
uint256 lastClaimed = lastClaim(tokenIndex);
if (lastClaimed >= EMISSION_END) return 0;
uint256 accumulatedQty = totalAccumulated(tokenIndex).sub(totalClaimed(tokenIndex));
return accumulatedQty;
}
function totalAccumulated(uint256 tokenIndex) public view override returns (uint256) {
require(block.timestamp > EMISSION_START, "Emission has not started yet");
require(IFaces(_facesAddress).ownerOf(tokenIndex) != address(0), "Owner cannot be 0 address");
require(tokenIndex < IFaces(_facesAddress).totalSupply(), "NFT at index has not been minted yet");
uint256 nowTime = block.timestamp < EMISSION_END ? block.timestamp : EMISSION_END;
uint256 elapsedTime = nowTime.sub(EMISSION_START);
uint256 yearsElapsed = elapsedTime.div(SECONDS_IN_A_YEAR);
uint256 totalAmountAccumulated = 0;
uint256 timeAccountedFor = 0;
for(uint year = 0; year < yearsElapsed; year++) {
uint256 emissionPerDayForYear = EMISSION_PER_DAY_YEARS[year];
uint256 yearAccumulated = emissionPerDayForYear.mul(365);
totalAmountAccumulated = totalAmountAccumulated.add(yearAccumulated);
timeAccountedFor = timeAccountedFor.add(SECONDS_IN_A_YEAR);
}
if(elapsedTime > timeAccountedFor && yearsElapsed < 10) {
uint256 remainingTime = elapsedTime.sub(timeAccountedFor);
uint256 currentEmissionRate = EMISSION_PER_DAY_YEARS[yearsElapsed];
uint256 remainingAccumulated = remainingTime.mul(currentEmissionRate).div(SECONDS_IN_A_DAY);
totalAmountAccumulated = totalAmountAccumulated.add(remainingAccumulated);
}
totalAmountAccumulated = totalAmountAccumulated.add(INITIAL_ALLOTMENT);
return totalAmountAccumulated;
}
function totalClaimed(uint256 tokenIndex) public view override returns (uint256) {
require(IFaces(_facesAddress).ownerOf(tokenIndex) != address(0), "Owner cannot be 0 address");
require(tokenIndex < IFaces(_facesAddress).totalSupply(), "NFT at index has not been minted yet");
uint256 claimed = uint256(_claimedAmount[tokenIndex]) >= 0 ? uint256(_claimedAmount[tokenIndex]) : 0;
return claimed;
}
function setFacesAddress(address facesAddress) onlyOwner public {
require(_facesAddress == address(0), "Already set");
_facesAddress = facesAddress;
}
function setAddonsAddress(address addonsAddress) onlyOwner public {
_addonsAddress = addonsAddress;
}
function claim(uint256[] memory tokenIndices) public returns (uint256) {
require(block.timestamp > EMISSION_START, "Emission has not started yet");
uint256 totalClaimQty = 0;
for (uint i = 0; i < tokenIndices.length; i++) {
require(tokenIndices[i] < IFaces(_facesAddress).totalSupply(), "NFT at index has not been minted yet");
for (uint j = i + 1; j < tokenIndices.length; j++) {
require(tokenIndices[i] != tokenIndices[j], "Duplicate token index");
}
uint tokenIndex = tokenIndices[i];
require(IFaces(_facesAddress).ownerOf(tokenIndex) == msg.sender, "Sender is not the owner");
uint256 claimQty = accumulated(tokenIndex);
if (claimQty != 0) {
_lastClaim[tokenIndex] = block.timestamp;
uint256 alreadyClaimed = _claimedAmount[tokenIndex];
_claimedAmount[tokenIndex] = alreadyClaimed.add(claimQty);
totalClaimQty = totalClaimQty.add(claimQty);
}
}
require(totalClaimQty != 0, "No accumulated SFT");
_mint(msg.sender, totalClaimQty);
return totalClaimQty;
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
if (msg.sender == _facesAddress) {
}
else if(_addonsAddress != address(0) && msg.sender == _addonsAddress) {
}
else {
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function burn(uint256 burnQuantity) public virtual override returns (bool) {
_burn(msg.sender, burnQuantity);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 10 的 10:SafeMath.sol
pragma solidity ^0.7.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/SFT.sol": "SFT"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"EMISSION_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"EMISSION_PER_DAY_YEARS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_4","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_5","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_6","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_7","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_8","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_PER_DAY_YEAR_9","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_START","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_ALLOTMENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_A_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_A_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"name":"accumulated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"burnQuantity","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIndices","type":"uint256[]"}],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"name":"lastClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addonsAddress","type":"address"}],"name":"setAddonsAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"facesAddress","type":"address"}],"name":"setFacesAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"name":"totalAccumulated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAccumulatedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"name":"totalClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]