aboutsummaryrefslogtreecommitdiff
path: root/contracts/arc20.sol
blob: d1af6a32887edc289b4da480db48e79e9c75efd8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// 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];
    }
}