aboutsummaryrefslogblamecommitdiff
path: root/contracts/arc20.sol
blob: a7fc9971e909d910374226d932555e06b57b8133 (plain) (tree)





















































































































































                                                                                                       
// 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];
    }
}