Skip to content

Commit 2d34a8d

Browse files
authored
refactor!: sdex burn ratio to uint64 (#895)
* refactor!: sdex burn ratio to uint64 The value for `sdexBurnOnDepositRatio` was previously stored as an uint32 which proved to be too small for shortDN. A new slot in the storage struct was defined for the new value as uint64. BREAKING CHANGE: this is breaking for consumers which expect a uint32, and it requires a storage update for the existing protocol instances * feat: add storage upgrade function * build: add upgrade script for v2 * chore: update upgrade script * chore: add new fallback deployment to upgrade script * chore: add validatation to upgrade script * chore: rename constant * chore: rename contract * chore: change script notice comment * chore: update lockfile * docs: add how to calculate the storage slot * docs: re-order natspec * chore: add asserts for script
1 parent 70174c6 commit 2d34a8d

12 files changed

+97
-14
lines changed

package-lock.json

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

script/55_UpgradeV2.s.sol

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity 0.8.26;
3+
4+
import { Script } from "forge-std/Script.sol";
5+
6+
import { UsdnWstethUsdConfig } from "./deploymentConfigs/UsdnWstethUsdConfig.sol";
7+
import { Utils } from "./utils/Utils.s.sol";
8+
9+
import { UsdnProtocolFallback } from "../src/UsdnProtocol/UsdnProtocolFallback.sol";
10+
import { UsdnProtocolImpl } from "../src/UsdnProtocol/UsdnProtocolImpl.sol";
11+
import { UsdnProtocolConstantsLibrary as Constants } from
12+
"../src/UsdnProtocol/libraries/UsdnProtocolConstantsLibrary.sol";
13+
import { IUsdnProtocol } from "../src/interfaces/UsdnProtocol/IUsdnProtocol.sol";
14+
15+
/**
16+
* @title Upgrade script
17+
* @notice This script is only made for upgrading the Usdn protocol from v1.x.x to v2.0.0.
18+
* @dev The sender must already have the `PROXY_UPGRADE_ROLE` before launching this script.
19+
*/
20+
contract UpgradeV2 is UsdnWstethUsdConfig, Script {
21+
IUsdnProtocol constant USDN_PROTOCOL = IUsdnProtocol(0x656cB8C6d154Aad29d8771384089be5B5141f01a);
22+
23+
/// @dev this is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
24+
bytes32 constant IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
25+
26+
Utils utils;
27+
28+
constructor() {
29+
utils = new Utils();
30+
}
31+
32+
function run()
33+
external
34+
returns (UsdnProtocolFallback newUsdnProtocolFallback_, UsdnProtocolImpl newUsdnProtocolImpl_)
35+
{
36+
utils.validateProtocol("UsdnProtocolImpl", "UsdnProtocolFallback");
37+
38+
require(
39+
USDN_PROTOCOL.hasRole(Constants.PROXY_UPGRADE_ROLE, msg.sender),
40+
"Sender does not have the permission to upgrade the protocol"
41+
);
42+
bytes32 oldImpl = vm.load(address(USDN_PROTOCOL), IMPL_SLOT);
43+
44+
vm.startBroadcast();
45+
46+
newUsdnProtocolFallback_ = new UsdnProtocolFallback(MAX_SDEX_BURN_RATIO, MAX_MIN_LONG_POSITION);
47+
newUsdnProtocolImpl_ = new UsdnProtocolImpl();
48+
USDN_PROTOCOL.upgradeToAndCall(
49+
address(newUsdnProtocolImpl_),
50+
abi.encodeWithSelector(UsdnProtocolImpl.initializeStorageV2.selector, address(newUsdnProtocolFallback_))
51+
);
52+
bytes32 newImpl = vm.load(address(USDN_PROTOCOL), IMPL_SLOT);
53+
require(oldImpl != newImpl, "Upgrade failed");
54+
require(address(uint160(uint256(newImpl))) == address(newUsdnProtocolImpl_), "Upgrade failed");
55+
require(USDN_PROTOCOL.getSdexBurnOnDepositRatio() > 0, "New storage not initialized");
56+
require(USDN_PROTOCOL.getFallbackAddress() == address(newUsdnProtocolFallback_), "New fallback not set");
57+
58+
vm.stopBroadcast();
59+
}
60+
}

src/UsdnProtocol/UsdnProtocolFallback.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ contract UsdnProtocolFallback is
314314
}
315315

316316
/// @inheritdoc IUsdnProtocolFallback
317-
function getSdexBurnOnDepositRatio() external view returns (uint32 ratio_) {
317+
function getSdexBurnOnDepositRatio() external view returns (uint64 ratio_) {
318318
return Utils._getMainStorage()._sdexBurnOnDepositRatio;
319319
}
320320

@@ -590,7 +590,7 @@ contract UsdnProtocolFallback is
590590
}
591591

592592
/// @inheritdoc IUsdnProtocolFallback
593-
function setSdexBurnOnDepositRatio(uint32 newRatio) external onlyRole(Constants.SET_PROTOCOL_PARAMS_ROLE) {
593+
function setSdexBurnOnDepositRatio(uint64 newRatio) external onlyRole(Constants.SET_PROTOCOL_PARAMS_ROLE) {
594594
Setters.setSdexBurnOnDepositRatio(MAX_SDEX_BURN_RATIO, newRatio);
595595
}
596596

src/UsdnProtocol/UsdnProtocolImpl.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ contract UsdnProtocolImpl is
5252
Setters.setInitialStorage(initStorage);
5353
}
5454

55+
/// @inheritdoc IUsdnProtocolImpl
56+
function initializeStorageV2(address newFallback) public reinitializer(2) {
57+
Storage storage s = Utils._getMainStorage();
58+
// sanity check, only do the upgrade if necessary
59+
if (s.__unused == 0 || s._sdexBurnOnDepositRatio > 0) {
60+
return;
61+
}
62+
s._sdexBurnOnDepositRatio = s.__unused;
63+
s._protocolFallbackAddr = newFallback;
64+
}
65+
5566
/**
5667
* @inheritdoc UUPSUpgradeable
5768
* @notice Verifies that the caller is allowed to upgrade the protocol.

src/UsdnProtocol/libraries/UsdnProtocolSettersLibrary.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ library UsdnProtocolSettersLibrary {
230230
}
231231

232232
/// @notice See {UsdnProtocolFallback.setSdexBurnOnDepositRatio}.
233-
function setSdexBurnOnDepositRatio(uint256 highestPossibleValue, uint32 newRatio) external {
233+
function setSdexBurnOnDepositRatio(uint256 highestPossibleValue, uint64 newRatio) external {
234234
Types.Storage storage s = Utils._getMainStorage();
235235

236236
if (newRatio > highestPossibleValue) {

src/UsdnProtocol/libraries/UsdnProtocolUtilsLibrary.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ library UsdnProtocolUtilsLibrary {
543543
* @param sdexBurnRatio The ratio of SDEX burned per minted USDN.
544544
* @return sdexToBurn_ The amount of SDEX tokens to burn.
545545
*/
546-
function _calcSdexToBurn(uint256 usdnAmount, uint32 sdexBurnRatio) internal pure returns (uint256 sdexToBurn_) {
546+
function _calcSdexToBurn(uint256 usdnAmount, uint64 sdexBurnRatio) internal pure returns (uint256 sdexToBurn_) {
547547
sdexToBurn_ = FixedPointMathLib.fullMulDivUp(usdnAmount, sdexBurnRatio, Constants.SDEX_BURN_ON_DEPOSIT_DIVISOR);
548548
}
549549

src/UsdnProtocol/libraries/UsdnProtocolVaultLibrary.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ library UsdnProtocolVaultLibrary {
604604
if (usdnToMintEstimated == 0) {
605605
revert IUsdnProtocolErrors.UsdnProtocolDepositTooSmall();
606606
}
607-
uint32 burnRatio = s._sdexBurnOnDepositRatio;
607+
uint64 burnRatio = s._sdexBurnOnDepositRatio;
608608
data_.sdexToBurn = Utils._calcSdexToBurn(usdnToMintEstimated, burnRatio);
609609
}
610610

src/interfaces/UsdnProtocol/IUsdnProtocolFallback.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ interface IUsdnProtocolFallback is IUsdnProtocolTypes {
336336
* @notice Gets the ratio of SDEX tokens to burn per minted USDN.
337337
* @return ratio_ The ratio (to be divided by SDEX_BURN_ON_DEPOSIT_DIVISOR).
338338
*/
339-
function getSdexBurnOnDepositRatio() external view returns (uint32 ratio_);
339+
function getSdexBurnOnDepositRatio() external view returns (uint64 ratio_);
340340

341341
/**
342342
* @notice Gets the amount of native tokens used as security deposit when opening a new position.
@@ -660,7 +660,7 @@ interface IUsdnProtocolFallback is IUsdnProtocolTypes {
660660
* constructor argument when the {UsdnProtocolFallback} contract is deployed and is stored in an immutable variable.
661661
* @param newRatio The new ratio.
662662
*/
663-
function setSdexBurnOnDepositRatio(uint32 newRatio) external;
663+
function setSdexBurnOnDepositRatio(uint64 newRatio) external;
664664

665665
/**
666666
* @notice Sets the security deposit value.

src/interfaces/UsdnProtocol/IUsdnProtocolImpl.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,13 @@ interface IUsdnProtocolImpl is
3131
* Any call with a function signature not present in this contract will be delegated to the fallback contract.
3232
*/
3333
function initializeStorage(InitStorage calldata initStorage) external;
34+
35+
/**
36+
* @notice Updates the protocol's storage from V1 to V2.
37+
* @dev This specifically re-assigns the value for `sdexBurnOnDepositRatio` to a new storage slot, and updates
38+
* the address of the fallback contract.
39+
* It can only be called once and should only be called if the protocol was initially deployed as V1.
40+
* @param newFallback The address of the new fallback contract that was deployed.
41+
*/
42+
function initializeStorageV2(address newFallback) external;
3443
}

src/interfaces/UsdnProtocol/IUsdnProtocolTypes.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ interface IUsdnProtocolTypes {
593593
* @param _positionFeeBps The position fee in basis points.
594594
* @param _vaultFeeBps The fee for vault deposits and withdrawals, in basis points.
595595
* @param _sdexRewardsRatioBps The ratio of SDEX rewards to send to the user (in basis points).
596-
* @param _sdexBurnOnDepositRatio The ratio of USDN to SDEX tokens to burn on deposit.
596+
* @param __unused Old slot for `_sdexBurnOnDepositRatio`.
597597
* @param _feeCollector The fee collector's address.
598598
* @param _securityDepositValue The deposit required for a new position.
599599
* @param _targetUsdnPrice The nominal (target) price of USDN (with _priceFeedDecimals).
@@ -624,6 +624,7 @@ interface IUsdnProtocolTypes {
624624
* @param _tickBitmap The bitmap used to quickly find populated ticks.
625625
* @param _protocolFallbackAddr The address of the fallback contract.
626626
* @param _nonce The user EIP712 nonce.
627+
* @param _sdexBurnOnDepositRatio The ratio of USDN to SDEX tokens to burn on deposit.
627628
*/
628629
struct Storage {
629630
// immutable
@@ -660,7 +661,7 @@ interface IUsdnProtocolTypes {
660661
uint16 _positionFeeBps;
661662
uint16 _vaultFeeBps;
662663
uint16 _sdexRewardsRatioBps;
663-
uint32 _sdexBurnOnDepositRatio;
664+
uint32 __unused;
664665
address _feeCollector;
665666
uint64 _securityDepositValue;
666667
uint128 _targetUsdnPrice;
@@ -692,6 +693,7 @@ interface IUsdnProtocolTypes {
692693
address _protocolFallbackAddr;
693694
// EIP712
694695
mapping(address => uint256) _nonce;
696+
uint64 _sdexBurnOnDepositRatio;
695697
}
696698

697699
/**
@@ -763,7 +765,7 @@ interface IUsdnProtocolTypes {
763765
uint16 positionFeeBps;
764766
uint16 vaultFeeBps;
765767
uint16 sdexRewardsRatioBps;
766-
uint32 sdexBurnOnDepositRatio;
768+
uint64 sdexBurnOnDepositRatio;
767769
address feeCollector;
768770
uint64 securityDepositValue;
769771
uint128 targetUsdnPrice;

test/unit/UsdnProtocol/Vault/_CalcSdexToBurn.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ contract TestUsdnProtocolCalcUsdnPrice is UsdnProtocolBaseFixture {
2222
* @custom:then The correct amount of SDEX to burn is returned
2323
*/
2424
function test_calcSdexToBurn() public view {
25-
uint32 burnRatio = protocol.getSdexBurnOnDepositRatio();
25+
uint64 burnRatio = protocol.getSdexBurnOnDepositRatio();
2626
uint256 burnRatioDivisor = Constants.SDEX_BURN_ON_DEPOSIT_DIVISOR;
2727
uint8 usdnDecimals = Constants.TOKENS_DECIMALS;
2828

test/unit/UsdnProtocol/utils/Handler.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ contract UsdnProtocolHandler is UsdnProtocolImpl, UsdnProtocolFallback, Test {
377377
return Utils._getOraclePrice(action, timestamp, actionId, priceData);
378378
}
379379

380-
function i_calcSdexToBurn(uint256 usdnAmount, uint32 sdexBurnRatio) external pure returns (uint256) {
380+
function i_calcSdexToBurn(uint256 usdnAmount, uint64 sdexBurnRatio) external pure returns (uint256) {
381381
return Utils._calcSdexToBurn(usdnAmount, sdexBurnRatio);
382382
}
383383

0 commit comments

Comments
 (0)