// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import {NativeAssets} from "./NativeAssets.sol";
contract ARC20 {
mapping (address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _assetID;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor(string memory name_, string memory symbol_, uint8 decimals_, uint256 assetID_) public {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
_assetID = assetID_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to represent the token.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
/**
* @dev Returns the total supply of `assetID` currently held by
* this contract.
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Returns the balance of `account` held in this contract.
*/
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
// Withdrawal/Deposit functionality
/**
* @dev Acknowledges the receipt of some amount of an Avalanche Native Token
* into the contract implementing this interface.
*/
function deposit() public {
uint256 updatedBalance = NativeAssets.assetBalance(address(this), _assetID);
uint256 depositAmount = updatedBalance - _totalSupply;
assert(depositAmount >= 0);
_balances[msg.sender] += depositAmount;
_totalSupply = updatedBalance;
emit Deposit(msg.sender, depositAmount);
}
/**
* @dev Emitted when `value` tokens are deposited from `depositor`
*/
event Deposit(address indexed depositor, uint256 value);
/**
* @dev Withdraws `value` of the underlying asset to the contract
* caller.
*/
function withdraw(uint256 value) public {
require(_balances[msg.sender] >= value, "Insufficient funds for withdrawal");
_balances[msg.sender] -= value;
_totalSupply -= value;
NativeAssets.assetCall(msg.sender, _assetID, value, "");
emit Withdrawal(msg.sender, value);
}
/**
* @dev Emitted when `value` tokens are withdrawn to `withdrawer`
*/
event Withdrawal(address indexed withdrawer, uint256 value);
/**
* @dev Returns the `assetID` of the underlying asset this contract handles.
*/
function assetID() external view returns (uint256) {
return _assetID;
}
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address to, uint256 value) public returns (bool success) {
require(_balances[msg.sender] >= value, "insufficient balance for transfer");
_balances[msg.sender] -= value; // deduct from sender's balance
_balances[to] += value; // add to recipient's balance
emit Transfer(msg.sender, to, value);
return true;
}
event Approval(address indexed owner, address indexed spender, uint256 value);
function approve(address spender, uint256 value)
public
returns (bool success)
{
_allowances[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value)
public
returns (bool success)
{
require(value <= _balances[from], "From address has insufficient balance to transfer");
require(value <= _allowances[from][msg.sender], "Insufficient allowance granted to sender");
_balances[from] -= value;
_balances[to] += value;
_allowances[from][msg.sender] -= value;
emit Transfer(from, to, value);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
}