-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathVaultToken.sol
110 lines (79 loc) · 4.32 KB
/
VaultToken.sol
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
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2024 PancakeSwap
pragma solidity ^0.8.0;
import {Currency} from "./types/Currency.sol";
import {IVaultToken} from "./interfaces/IVaultToken.sol";
/// @dev This contract is a modified version of the ERC6909 implementation:
/// 1. totalSupply is removed
/// 2. tokenId is changed to Currency to fit our use case
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC6909.sol)
/// @notice Users are allowed to store their surplus tokens i.e. unsettled balance that the pool
/// owed to user in the vault, and they will be able to withdraw them or use them to settle future
/// transactions. VaultToken is designed as a minimum implementation to achieve this goal. It keeps
/// track of users' surplus tokens and allows users to approve others to spend their tokens.
abstract contract VaultToken is IVaultToken {
/*//////////////////////////////////////////////////////////////
ERC6909 STORAGE
//////////////////////////////////////////////////////////////*/
mapping(address owner => mapping(address operator => bool isOperator)) public isOperator;
mapping(address owner => mapping(Currency currency => uint256 balance)) public balanceOf;
mapping(address owner => mapping(address spender => mapping(Currency currency => uint256 amount))) public allowance;
/*//////////////////////////////////////////////////////////////
ERC6909 LOGIC
//////////////////////////////////////////////////////////////*/
function transfer(address receiver, Currency currency, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender][currency] -= amount;
balanceOf[receiver][currency] += amount;
emit Transfer(msg.sender, msg.sender, receiver, currency, amount);
return true;
}
function transferFrom(address sender, address receiver, Currency currency, uint256 amount)
public
virtual
returns (bool)
{
if (msg.sender != sender && !isOperator[sender][msg.sender]) {
uint256 allowed = allowance[sender][msg.sender][currency];
if (allowed != type(uint256).max) allowance[sender][msg.sender][currency] -= amount;
}
balanceOf[sender][currency] -= amount;
balanceOf[receiver][currency] += amount;
emit Transfer(msg.sender, sender, receiver, currency, amount);
return true;
}
function approve(address spender, Currency currency, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender][currency] = amount;
emit Approval(msg.sender, spender, currency, amount);
return true;
}
function setOperator(address operator, bool approved) public virtual returns (bool) {
isOperator[msg.sender][operator] = approved;
emit OperatorSet(msg.sender, operator, approved);
return true;
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
|| interfaceId == 0xb2e69f8a; // ERC165 Interface ID for ERC6909
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address receiver, Currency currency, uint256 amount) internal virtual {
balanceOf[receiver][currency] += amount;
emit Transfer(msg.sender, address(0), receiver, currency, amount);
}
function _burn(address sender, Currency currency, uint256 amount) internal virtual {
balanceOf[sender][currency] -= amount;
emit Transfer(msg.sender, sender, address(0), currency, amount);
}
function _burnFrom(address from, Currency currency, uint256 amount) internal virtual {
if (msg.sender != from && !isOperator[from][msg.sender]) {
uint256 allowed = allowance[from][msg.sender][currency];
if (allowed != type(uint256).max) allowance[from][msg.sender][currency] -= amount;
}
_burn(from, currency, amount);
}
}