Skip to content

Commit e380d1a

Browse files
authored
Feat/stable token v3 (#607)
### Description This Pr adds the StableTokenV3 contracts: ### StableTokenV3.sol This contract adds logic for Mentov3 while still being storage-compatible with our previous StableTokenV2 implementation. added logic: - minter role: needed for LiquityV2 contracts as well as Wormhole cross-chain ntt manager support - burner role: needed for LiquityV2 contracts as well as Wormhole cross-chain ntt manager support - operator role: special direct transfer rights needed for stability pool in liquityV2 Storage Layout: StableTokenV2.sol: <img width="1288" height="702" alt="image" src="https://github.com/user-attachments/assets/d4a8f143-2db8-4e0a-8f91-165f966ff5cf" /> StableTokenV3.sol: <img width="1308" height="779" alt="image" src="https://github.com/user-attachments/assets/9acc6722-6388-46de-8f92-81fc394912de" /> ### StableTokenV3CrossChain.sol Naming not great open for any ideas 😁 This is a simple ERC20PermitUpgradeable with a minter and burner role. Since we don't need to be backwards compatible on other chains we also don't need to inherit from the patched versions. The minter and burner roles are necessary for FPMM's and wormhole NTTMangers. If we decide that we also need to be LiquityV2 compatible on other chains we have to add the operator role as well as the corresponding direct transfer functions. ### Other changes - remove transferWithComment since this was only for Valora ### Tested - V3 unit tests - V3 CrossChain unit tests - V2ToV3 migration fork test ### Related issues ### Backwards compatibility ### Documentation
1 parent c6d81fa commit e380d1a

11 files changed

Lines changed: 1383 additions & 481 deletions
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.8.24;
3+
import {
4+
IERC20PermitUpgradeable
5+
} from "openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
6+
7+
/**
8+
* @title IStableTokenSpoke
9+
* @notice Interface for the StableTokenSpoke contract.
10+
*/
11+
interface IStableTokenSpoke is IERC20PermitUpgradeable {
12+
/**
13+
* @notice Initializes a StableTokenSpoke.
14+
* @param _name The name of the stable token (English)
15+
* @param _symbol A short symbol identifying the token (e.g. "cUSD")
16+
* @param initialBalanceAddresses Array of addresses with an initial balance.
17+
* @param initialBalanceValues Array of balance values corresponding to initialBalanceAddresses.
18+
* @param _minters The addresses that are allowed to mint.
19+
* @param _burners The addresses that are allowed to burn.
20+
*/
21+
function initialize(
22+
string calldata _name,
23+
string calldata _symbol,
24+
address[] calldata initialBalanceAddresses,
25+
uint256[] calldata initialBalanceValues,
26+
address[] calldata _minters,
27+
address[] calldata _burners
28+
) external;
29+
/**
30+
* @notice Sets the minter role for an address.
31+
* @param _minter The address of the minter.
32+
* @param _isMinter The boolean value indicating if the address is a minter.
33+
*/
34+
function setMinter(address _minter, bool _isMinter) external;
35+
36+
/**
37+
* @notice Sets the burner role for an address.
38+
* @param _burner The address of the burner.
39+
* @param _isBurner The boolean value indicating if the address is a burner.
40+
*/
41+
function setBurner(address _burner, bool _isBurner) external;
42+
43+
/**
44+
* @notice Mints new StableToken and gives it to 'to'.
45+
* @param to The account for which to mint tokens.
46+
* @param value The amount of StableToken to mint.
47+
*/
48+
function mint(address to, uint256 value) external returns (bool);
49+
50+
/**
51+
* @notice Burns StableToken from the balance of msg.sender.
52+
* @param value The amount of StableToken to burn.
53+
*/
54+
function burn(uint256 value) external returns (bool);
55+
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.8.24;
3+
4+
/**
5+
* @title IStableTokenV3
6+
* @notice Interface for the StableTokenV3 contract.
7+
*/
8+
interface IStableTokenV3 {
9+
/**
10+
* @notice Initializes a StableTokenV3.
11+
* @param _name The name of the stable token (English)
12+
* @param _symbol A short symbol identifying the token (e.g. "cUSD")
13+
* @param initialBalanceAddresses Array of addresses with an initial balance.
14+
* @param initialBalanceValues Array of balance values corresponding to initialBalanceAddresses.
15+
* @param _minters The addresses that are allowed to mint.
16+
* @param _burners The addresses that are allowed to burn.
17+
* @param _operators The addresses that are allowed to call the operator functions.
18+
*/
19+
function initialize(
20+
string calldata _name,
21+
string calldata _symbol,
22+
address[] calldata initialBalanceAddresses,
23+
uint256[] calldata initialBalanceValues,
24+
address[] calldata _minters,
25+
address[] calldata _burners,
26+
address[] calldata _operators
27+
) external;
28+
29+
/**
30+
* @notice Initializes a StableTokenV3 contract
31+
* when upgrading from StableTokenV2.sol.
32+
* It sets the addresses of the minters, burners, and operators.
33+
* @dev This function is only callable once.
34+
* @param _minters The addresses that are allowed to mint.
35+
* @param _burners The addresses that are allowed to burn.
36+
* @param _operators The addresses that are allowed to call the operator functions.
37+
*/
38+
function initializeV3(
39+
address[] calldata _minters,
40+
address[] calldata _burners,
41+
address[] calldata _operators
42+
) external;
43+
44+
/**
45+
* @notice Sets the operator role for an address.
46+
* @param _operator The address of the operator.
47+
* @param _isOperator The boolean value indicating if the address is an operator.
48+
*/
49+
function setOperator(address _operator, bool _isOperator) external;
50+
51+
/**
52+
* @notice Sets the minter role for an address.
53+
* @param _minter The address of the minter.
54+
* @param _isMinter The boolean value indicating if the address is a minter.
55+
*/
56+
function setMinter(address _minter, bool _isMinter) external;
57+
58+
/**
59+
* @notice Sets the burner role for an address.
60+
* @param _burner The address of the burner.
61+
* @param _isBurner The boolean value indicating if the address is a burner.
62+
*/
63+
function setBurner(address _burner, bool _isBurner) external;
64+
65+
/**
66+
* From openzeppelin's IERC20.sol
67+
* @dev Returns the amount of tokens in existence.
68+
*/
69+
function totalSupply() external view returns (uint256);
70+
71+
/**
72+
* From openzeppelin's IERC20.sol
73+
* @dev Returns the amount of tokens owned by `account`.
74+
*/
75+
function balanceOf(address account) external view returns (uint256);
76+
77+
/**
78+
* From openzeppelin's IERC20.sol
79+
* @dev Moves `amount` tokens from the caller's account to `to`.
80+
*
81+
* Returns a boolean value indicating whether the operation succeeded.
82+
*
83+
* Emits a {Transfer} event.
84+
*/
85+
function transfer(address recipient, uint256 amount) external returns (bool);
86+
87+
/**
88+
* From openzeppelin's IERC20.sol
89+
* @dev Returns the remaining number of tokens that `spender` will be
90+
* allowed to spend on behalf of `owner` through {transferFrom}. This is
91+
* zero by default.
92+
*
93+
* This value changes when {approve} or {transferFrom} are called.
94+
*/
95+
function allowance(address owner, address spender) external view returns (uint256);
96+
97+
/**
98+
* From openzeppelin's IERC20.sol
99+
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
100+
*
101+
* Returns a boolean value indicating whether the operation succeeded.
102+
*
103+
* IMPORTANT: Beware that changing an allowance with this method brings the risk
104+
* that someone may use both the old and the new allowance by unfortunate
105+
* transaction ordering. One possible solution to mitigate this race
106+
* condition is to first reduce the spender's allowance to 0 and set the
107+
* desired value afterwards:
108+
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
109+
*
110+
* Emits an {Approval} event.
111+
*/
112+
function approve(address spender, uint256 amount) external returns (bool);
113+
114+
/**
115+
* From openzeppelin's IERC20.sol
116+
* @dev Moves `amount` tokens from `from` to `to` using the
117+
* allowance mechanism. `amount` is then deducted from the caller's
118+
* allowance.
119+
*
120+
* Returns a boolean value indicating whether the operation succeeded.
121+
*
122+
* Emits a {Transfer} event.
123+
*/
124+
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
125+
126+
/**
127+
* @notice Mints new StableToken and gives it to 'to'.
128+
* @param to The account for which to mint tokens.
129+
* @param value The amount of StableToken to mint.
130+
*/
131+
function mint(address to, uint256 value) external returns (bool);
132+
133+
/**
134+
* @notice Burns StableToken from the balance of msg.sender.
135+
* @param value The amount of StableToken to burn.
136+
*/
137+
function burn(uint256 value) external returns (bool);
138+
139+
/**
140+
* From openzeppelin's IERC20PermitUpgradeable.sol
141+
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
142+
* given ``owner``'s signed approval.
143+
*
144+
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
145+
* ordering also apply here.
146+
*
147+
* Emits an {Approval} event.
148+
*
149+
* Requirements:
150+
*
151+
* - `spender` cannot be the zero address.
152+
* - `deadline` must be a timestamp in the future.
153+
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
154+
* over the EIP712-formatted function arguments.
155+
* - the signature must use ``owner``'s current nonce (see {nonces}).
156+
*
157+
* For more information on the signature format, see the
158+
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
159+
* section].
160+
*/
161+
function permit(
162+
address owner,
163+
address spender,
164+
uint256 value,
165+
uint256 deadline,
166+
uint8 v,
167+
bytes32 r,
168+
bytes32 s
169+
) external;
170+
171+
/**
172+
* @notice Transfer token from a specified address to the stability pool.
173+
* @param _sender The address to transfer from.
174+
* @param _poolAddress The address of the pool to transfer to.
175+
* @param _amount The amount to be transferred.
176+
*/
177+
function sendToPool(address _sender, address _poolAddress, uint256 _amount) external;
178+
179+
/**
180+
* @notice Transfer token to a specified address from the stability pool.
181+
* @param _poolAddress The address of the pool to transfer from
182+
* @param _receiver The address to transfer to.
183+
* @param _amount The amount to be transferred.
184+
*/
185+
function returnFromPool(address _poolAddress, address _receiver, uint256 _amount) external;
186+
187+
/**
188+
* @notice Reserve balance for making payments for gas in this StableToken currency.
189+
* @param from The account to reserve balance from
190+
* @param value The amount of balance to reserve
191+
* @dev Note that this function is called by the protocol when paying for tx fees in this
192+
* currency. After the tx is executed, gas is refunded to the sender and credited to the
193+
* various tx fee recipients via a call to `creditGasFees`.
194+
*/
195+
function debitGasFees(address from, uint256 value) external;
196+
197+
/**
198+
* @notice Alternative function to credit balance after making payments
199+
* for gas in this StableToken currency.
200+
* @param from The account to debit balance from
201+
* @param feeRecipient Coinbase address
202+
* @param gatewayFeeRecipient Gateway address
203+
* @param communityFund Community fund address
204+
* @param refund amount to be refunded by the VM
205+
* @param tipTxFee Coinbase fee
206+
* @param baseTxFee Community fund fee
207+
* @param gatewayFee Gateway fee
208+
* @dev Note that this function is called by the protocol when paying for tx fees in this
209+
* currency. Before the tx is executed, gas is debited from the sender via a call to
210+
* `debitGasFees`.
211+
*/
212+
function creditGasFees(
213+
address from,
214+
address feeRecipient,
215+
address gatewayFeeRecipient,
216+
address communityFund,
217+
uint256 refund,
218+
uint256 tipTxFee,
219+
uint256 gatewayFee,
220+
uint256 baseTxFee
221+
) external;
222+
}

0 commit comments

Comments
 (0)