generated from ZeframLou/foundry-template
-
Notifications
You must be signed in to change notification settings - Fork 15
/
PerpetualYieldToken.sol
106 lines (88 loc) · 3.01 KB
/
PerpetualYieldToken.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
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.13;
import {Gate} from "./Gate.sol";
import {BaseERC20} from "./lib/BaseERC20.sol";
/// @title PerpetualYieldToken
/// @author zefram.eth
/// @notice The ERC20 contract representing perpetual yield tokens
contract PerpetualYieldToken is BaseERC20 {
/// -----------------------------------------------------------------------
/// Constructor
/// -----------------------------------------------------------------------
constructor(Gate gate_, address vault_)
BaseERC20(
gate_.perpetualYieldTokenName(vault_),
gate_.perpetualYieldTokenSymbol(vault_),
gate_,
vault_
)
{}
/// -----------------------------------------------------------------------
/// ERC20 overrides
/// -----------------------------------------------------------------------
function transfer(address to, uint256 amount)
public
virtual
override
returns (bool)
{
// load balances to save gas
uint256 fromBalance = balanceOf[msg.sender];
uint256 toBalance = balanceOf[to];
// call transfer hook
gate.beforePerpetualYieldTokenTransfer(
msg.sender,
to,
amount,
fromBalance,
toBalance
);
// do transfer
// skip during self transfers since toBalance is cached
// which leads to free minting, a critical issue
if (msg.sender != to) {
balanceOf[msg.sender] = fromBalance - amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] = toBalance + amount;
}
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
// load balances to save gas
uint256 fromBalance = balanceOf[from];
uint256 toBalance = balanceOf[to];
// call transfer hook
gate.beforePerpetualYieldTokenTransfer(
from,
to,
amount,
fromBalance,
toBalance
);
// update allowance
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max)
allowance[from][msg.sender] = allowed - amount;
// do transfer
// skip during self transfers since toBalance is cached
// which leads to free minting, a critical issue
if (from != to) {
balanceOf[from] = fromBalance - amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] = toBalance + amount;
}
}
emit Transfer(from, to, amount);
return true;
}
}