-
Notifications
You must be signed in to change notification settings - Fork 327
/
BackingEigen.sol
138 lines (118 loc) · 5.4 KB
/
BackingEigen.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
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
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;
import "@openzeppelin-v4.9.0/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin-upgrades-v4.9.0/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol";
import "@openzeppelin-upgrades-v4.9.0/contracts/access/OwnableUpgradeable.sol";
contract BackingEigen is OwnableUpgradeable, ERC20VotesUpgradeable {
/// CONSTANTS & IMMUTABLES
/// @notice the address of the wrapped Eigen token EIGEN
IERC20 public immutable EIGEN;
/// STORAGE
/// @notice the timestamp after which transfer restrictions are disabled
uint256 public transferRestrictionsDisabledAfter;
/// @notice mapping of addresses that are allowed to transfer tokens to any address
mapping(address => bool) public allowedFrom;
/// @notice mapping of addresses that are allowed to receive tokens from any address
mapping(address => bool) public allowedTo;
/// @notice event emitted when the allowedFrom status of an address is set
event SetAllowedFrom(address indexed from, bool isAllowedFrom);
/// @notice event emitted when the allowedTo status of an address is set
event SetAllowedTo(address indexed to, bool isAllowedTo);
/// @notice event emitted when the transfer restrictions are disabled
event TransferRestrictionsDisabled();
/// @notice event emitted when the EIGEN token is backed
event Backed();
constructor(IERC20 _EIGEN) {
EIGEN = _EIGEN;
_disableInitializers();
}
/**
* @notice An initializer function that sets initial values for the contract's state variables.
*/
function initialize(address initialOwner) public initializer {
__Ownable_init();
__ERC20_init("Backing Eigen", "bEIGEN");
_transferOwnership(initialOwner);
__ERC20Permit_init("bEIGEN");
// set transfer restrictions to be disabled at type(uint256).max to be set down later
transferRestrictionsDisabledAfter = type(uint256).max;
// the EIGEN contract should be allowed to transfer tokens to any address for unwrapping
// likewise, anyone should be able to transfer bEIGEN to EIGEN for wrapping
_setAllowedFrom(address(EIGEN), true);
_setAllowedTo(address(EIGEN), true);
// Mint the entire supply of EIGEN - this is a one-time event that
// ensures bEIGEN fully backs EIGEN.
_mint(address(EIGEN), EIGEN.totalSupply());
emit Backed();
}
/// EXTERNAL FUNCTIONS
/**
* @notice This function allows the owner to set the allowedFrom status of an address
* @param from the address whose allowedFrom status is being set
* @param isAllowedFrom the new allowedFrom status
*/
function setAllowedFrom(address from, bool isAllowedFrom) external onlyOwner {
_setAllowedFrom(from, isAllowedFrom);
}
/**
* @notice This function allows the owner to set the allowedTo status of an address
* @param to the address whose allowedTo status is being set
* @param isAllowedTo the new allowedTo status
*/
function setAllowedTo(address to, bool isAllowedTo) external onlyOwner {
_setAllowedTo(to, isAllowedTo);
}
/**
* @notice Allows the owner to disable transfer restrictions
*/
function disableTransferRestrictions() external onlyOwner {
require(
transferRestrictionsDisabledAfter == type(uint256).max,
"BackingEigen.disableTransferRestrictions: transfer restrictions are already disabled"
);
transferRestrictionsDisabledAfter = 0;
emit TransferRestrictionsDisabled();
}
/// VIEW FUNCTIONS
/**
* @dev Clock used for flagging checkpoints. Has been overridden to implement timestamp based
* checkpoints (and voting).
*/
function clock() public view override returns (uint48) {
return SafeCastUpgradeable.toUint48(block.timestamp);
}
/**
* @dev Machine-readable description of the clock as specified in EIP-6372.
* Has been overridden to inform callers that this contract uses timestamps instead of block numbers, to match `clock()`
*/
// solhint-disable-next-line func-name-mixedcase
function CLOCK_MODE() public pure override returns (string memory) {
return "mode=timestamp";
}
/// INTERNAL FUNCTIONS
function _setAllowedFrom(address from, bool isAllowedFrom) internal {
allowedFrom[from] = isAllowedFrom;
emit SetAllowedFrom(from, isAllowedFrom);
}
function _setAllowedTo(address to, bool isAllowedTo) internal {
allowedTo[to] = isAllowedTo;
emit SetAllowedTo(to, isAllowedTo);
}
/**
* @notice Overrides the beforeTokenTransfer function to enforce transfer restrictions
* @param from the address tokens are being transferred from
* @param to the address tokens are being transferred to
* @param amount the amount of tokens being transferred
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {
// if transfer restrictions are enabled
if (block.timestamp <= transferRestrictionsDisabledAfter) {
// if both from and to are not whitelisted
require(
allowedFrom[from] || allowedTo[to] || from == address(0),
"BackingEigen._beforeTokenTransfer: from or to must be whitelisted"
);
}
super._beforeTokenTransfer(from, to, amount);
}
}