Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NES-255] make pUSD a ComponentToken #97

Merged
merged 68 commits into from
Dec 2, 2024
Merged
Changes from 1 commit
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
2131910
[NES-254] add adapter contract for pUSD
eyqs Nov 13, 2024
e415bc9
add vault for pUSD
ungaro Nov 13, 2024
51e5d53
remove incorrect include
ungaro Nov 13, 2024
9656816
keep pUSD as ERC20 and remove unnecessary functions
ungaro Nov 13, 2024
69467dd
remove comment
ungaro Nov 13, 2024
35ca154
fmt
ungaro Nov 13, 2024
c613ac9
remove hook
ungaro Nov 13, 2024
697c4f9
make pUSD a ComponentToken
ungaro Nov 13, 2024
03dcdd1
make pUSD a ComponentToken and update Deployment Script
ungaro Nov 13, 2024
2452ef9
change storage location
ungaro Nov 13, 2024
9fc98c6
remove erc4626
ungaro Nov 13, 2024
1636d22
update pUSD storage slot
ungaro Nov 13, 2024
300f1b4
pUSD is Initializable, ERC20Upgradeable, AccessControlUpgradeable, UU…
ungaro Nov 13, 2024
9e4f883
merge main
ungaro Nov 13, 2024
00cd67b
fix overrides
ungaro Nov 13, 2024
270dd48
update description
ungaro Nov 13, 2024
5bc1b2f
add test for pUSD - WIP
ungaro Nov 13, 2024
1ce0e5a
add mockvault for pUSD
ungaro Nov 13, 2024
47cb601
change initialization modifier to onlyInitializing
ungaro Nov 14, 2024
f5773db
remove pausable
ungaro Nov 14, 2024
b00649d
finish preliminary tests, fix some bugs with MockVault and pUSD
ungaro Nov 14, 2024
013f0eb
93.9% coverage for pUSD - rest is just assembly
ungaro Nov 14, 2024
f034359
remove comments
ungaro Nov 14, 2024
5521e69
add IVault interface
ungaro Nov 14, 2024
2ab5bb8
forge fmt
ungaro Nov 14, 2024
4fdd93f
better handling of convertToShares, convertToAssets, make tests 100% …
ungaro Nov 14, 2024
030869c
forge fmt
ungaro Nov 14, 2024
ff2f659
add extra comment
ungaro Nov 14, 2024
93a2f34
add reentrancy check
ungaro Nov 14, 2024
269841d
implementing some audit findings & ComponentToken precision test checks
ungaro Nov 14, 2024
396cff3
leave conversion functions unimplemented and force integrators to imp…
ungaro Nov 14, 2024
d6537de
add NatSpec comments for functions
ungaro Nov 14, 2024
d5d2a61
remove componenttoken comments
ungaro Nov 14, 2024
999adcb
deployment script for pUSD
ungaro Nov 14, 2024
114516a
add pUSD contract update
ungaro Nov 15, 2024
5e1f0cf
add more tests from pUSD
ungaro Nov 18, 2024
354bc4d
forge install: solmate
ungaro Nov 18, 2024
9093df0
change vault to teller
ungaro Nov 18, 2024
5d827b6
change deploy&upgrade pUSD scripts, update componenttoken _authorizeU…
ungaro Nov 18, 2024
7ba1fe4
change deposit and redeem functions
ungaro Nov 19, 2024
9dae01f
final changes, tests etc.
ungaro Nov 19, 2024
3111677
confirm teller.deposit works, add working test-case on-chain (pUSDPlu…
ungaro Nov 20, 2024
e0f73a8
redeem works through AtomicRequest, change proxy comments
ungaro Nov 21, 2024
e2a9c25
add boringvault struct, change related deployment and upgrade address…
ungaro Nov 22, 2024
bb540e8
fix tests and deployment/upgrade scripts
ungaro Nov 22, 2024
38608c3
remove pUSD deployment from DeployNestContracts
ungaro Nov 22, 2024
200ac3d
remove setBeforeTransferHook from mockvault
ungaro Nov 22, 2024
1deb5b9
fix conflicts
ungaro Nov 22, 2024
bb8000c
fix conflict that doesn't exist
ungaro Nov 22, 2024
fc49f7c
100% coverage on pUSD + added missing mocks
ungaro Nov 22, 2024
72b82cd
add pragma to MockUSDC
ungaro Nov 22, 2024
d2a1785
run everything without errors even RPC address is not provided for on…
ungaro Nov 25, 2024
db3516c
change balanceof to return vault's balance
ungaro Nov 25, 2024
0a0a9a8
change balanceOf, previewDeposit and previewRedeem functions
ungaro Nov 25, 2024
761855b
add decimals to interface
ungaro Nov 27, 2024
c270097
passing tests
ungaro Nov 29, 2024
0ea586a
add usdc & usdt, update deploy scripts, add missing tests
ungaro Dec 1, 2024
fcb7a30
forge fmt
ungaro Dec 1, 2024
d85a529
add IAccountantWithRateProviders, IRateProvider, Ilens and mock contr…
ungaro Dec 1, 2024
e152ec0
add lens and accountant
ungaro Dec 1, 2024
34b4546
balanceof and balanceofinassets
ungaro Dec 1, 2024
e8cbe26
all tests pass
ungaro Dec 1, 2024
145244a
100% coverage for pUSD, real calculations for converttoshares, conver…
ungaro Dec 1, 2024
4ed12dc
add nonreentrant
ungaro Dec 1, 2024
723a392
add assetsof
ungaro Dec 1, 2024
ee714c1
balanceOfInAssets to be renamed assetsof
ungaro Dec 1, 2024
8ae47f0
merge main
ungaro Dec 1, 2024
869fd2f
formatting
ungaro Dec 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
change deploy&upgrade pUSD scripts, update componenttoken _authorizeU…
…pgrade to be virtual, add explicit pUSDProxy contract
ungaro committed Nov 18, 2024
commit 5d827b6775e0c6e90a4a886238eafa672eb097e4
1 change: 1 addition & 0 deletions nest/script/DeploypUSD.s.sol
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Script } from "forge-std/Script.sol";
import { console2 } from "forge-std/console2.sol";

import { pUSDProxy } from "../src/proxy/pUSDProxy.sol";
import { pUSD } from "../src/token/pUSD.sol";

contract DeploypUSD is Script {
9 changes: 5 additions & 4 deletions nest/script/UpgradeNestContracts.s.sol
Original file line number Diff line number Diff line change
@@ -7,15 +7,16 @@ import { Test } from "forge-std/Test.sol";
import { console2 } from "forge-std/console2.sol";

import { AggregateToken } from "../src/AggregateToken.sol";
import { AggregateTokenProxy } from "../src/proxy/AggregateTokenProxy.sol";

import { IComponentToken } from "../src/interfaces/IComponentToken.sol";
import { AggregateTokenProxy } from "../src/proxy/AggregateTokenProxy.sol";

contract UpgradeNestContracts is Script, Test {

address private constant NEST_ADMIN_ADDRESS = 0xb015762405De8fD24d29A6e0799c12e0Ea81c1Ff;
address private constant NEST_ADMIN_ADDRESS = 0xb015762405De8fD24d29A6e0799c12e0Ea81c1Ff;
UUPSUpgradeable private constant AGGREGATE_TOKEN_PROXY =
UUPSUpgradeable(payable(0x659619AEdf381c3739B0375082C2d61eC1fD8835));

// Add the component token addresses
address private constant ASSET_TOKEN = 0xF66DFD0A9304D3D6ba76Ac578c31C84Dc0bd4A00;

@@ -54,7 +55,7 @@ contract UpgradeNestContracts is Script, Test {
// Verify the component tokens are in the list
IComponentToken[] memory tokens = aggregateToken.getComponentTokenList();
console2.log("Number of component tokens:", tokens.length);
for (uint i = 0; i < tokens.length; i++) {
for (uint256 i = 0; i < tokens.length; i++) {
console2.log("Component token", i, ":", address(tokens[i]));
}
}
109 changes: 109 additions & 0 deletions nest/script/UpgradepUSD.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { ERC1967Utils } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";

import { Script } from "forge-std/Script.sol";
import { Test } from "forge-std/Test.sol";
import { console2 } from "forge-std/console2.sol";

import { pUSD } from "../src/token/pUSD.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";

contract UpgradePUSD is Script, Test {

// Constants
address private constant ADMIN_ADDRESS = 0xb015762405De8fD24d29A6e0799c12e0Ea81c1Ff;
address private constant PUSD_PROXY = 0x2DEc3B6AdFCCC094C31a2DCc83a43b5042220Ea2;
address private constant USDC_ADDRESS = 0x401eCb1D350407f13ba348573E5630B83638E30D;
address private constant VAULT_TOKEN = 0xe644F07B1316f28a7F134998e021eA9f7135F351;

// Current state tracking
pUSD public currentImplementation;
string public currentName;
string public currentSymbol;
uint8 public currentDecimals;
address public currentVault;
uint256 public currentTotalSupply;

function setUp() public {
// Get current implementation address
bytes32 implementationSlot = ERC1967Utils.IMPLEMENTATION_SLOT;
address currentImplementationAddr = address(uint160(uint256(vm.load(PUSD_PROXY, implementationSlot))));
console2.log("Current Implementation Address:", currentImplementationAddr);

// Verify UPGRADER_ROLE
bool hasUpgraderRole = pUSD(PUSD_PROXY).hasRole(pUSD(PUSD_PROXY).UPGRADER_ROLE(), ADMIN_ADDRESS);
console2.log("ADMIN_ADDRESS:", ADMIN_ADDRESS);
console2.log("Has UPGRADER_ROLE:", hasUpgraderRole);

// Store current state before upgrade
currentImplementation = pUSD(PUSD_PROXY);
currentName = currentImplementation.name();
currentSymbol = currentImplementation.symbol();
currentDecimals = currentImplementation.decimals();
currentVault = currentImplementation.vault();
currentTotalSupply = currentImplementation.totalSupply();

console2.log("Current Implementation State:");
console2.log("Name:", currentName);
console2.log("Symbol:", currentSymbol);
console2.log("Decimals:", currentDecimals);
console2.log("Vault:", currentVault);
console2.log("Total Supply:", currentTotalSupply);

// Store current state before upgrade
currentImplementation = pUSD(PUSD_PROXY);
}

function testSimulateUpgrade() public {
// Deploy new implementation in test environment
vm.startPrank(ADMIN_ADDRESS);

pUSD newImplementation = new pUSD();
UUPSUpgradeable(payable(PUSD_PROXY)).upgradeToAndCall(address(newImplementation), "");

pUSD upgradedToken = pUSD(PUSD_PROXY);

// Verify state preservation
assertEq(upgradedToken.name(), currentName, "Name changed");
assertEq(upgradedToken.symbol(), currentSymbol, "Symbol changed");
assertEq(upgradedToken.decimals(), currentDecimals, "Decimals changed");
assertEq(upgradedToken.vault(), currentVault, "Vault changed");
assertEq(upgradedToken.totalSupply(), currentTotalSupply, "Total supply changed");

vm.stopPrank();
console2.log("Upgrade simulation successful");
}

function run() external {
vm.startBroadcast(ADMIN_ADDRESS);

// Deploy new implementation
pUSD newImplementation = new pUSD();
console2.log("New Implementation Address:", address(newImplementation));

// Get current version
pUSD currentProxy = pUSD(PUSD_PROXY);
uint256 currentVersion = currentProxy.version();
console2.log("Current Version:", currentVersion);

// First upgrade the implementation
UUPSUpgradeable(payable(PUSD_PROXY)).upgradeToAndCall(
address(newImplementation),
"" // No initialization data for the upgrade
);

// Then call reinitialize separately
pUSD(PUSD_PROXY).reinitialize(ADMIN_ADDRESS, IERC20(USDC_ADDRESS), VAULT_TOKEN);

// Verify the upgrade
uint256 newVersion = pUSD(PUSD_PROXY).version();
require(newVersion == currentVersion + 1, "Version not incremented");
console2.log("New Version:", newVersion);

vm.stopBroadcast();
}

}
2 changes: 1 addition & 1 deletion nest/src/ComponentToken.sol
Original file line number Diff line number Diff line change
@@ -176,7 +176,7 @@ abstract contract ComponentToken is
*/
function _authorizeUpgrade(
address newImplementation
) internal override(UUPSUpgradeable) onlyRole(UPGRADER_ROLE) { }
) internal virtual override(UUPSUpgradeable) onlyRole(UPGRADER_ROLE) { }

/// @inheritdoc IERC165
function supportsInterface(
26 changes: 26 additions & 0 deletions nest/src/proxy/pUSDProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

/**
* @title USDTProxy
* @author Eugene Y. Q. Shen
* @notice Proxy contract for USDT
*/
contract pUSDProxy is ERC1967Proxy {

/// @notice Indicates a failure because transferring ETH to the proxy is unsupported
error ETHTransferUnsupported();

/// @notice Name of the proxy, used to ensure each named proxy has unique bytecode
bytes32 public constant PROXY_NAME = keccak256("pUSDProxy");

constructor(address logic, bytes memory data) ERC1967Proxy(logic, data) { }

/// @dev Fallback function to silence compiler warnings
receive() external payable {
revert ETHTransferUnsupported();
}

}
53 changes: 50 additions & 3 deletions nest/src/token/pUSD.sol
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@
pragma solidity ^0.8.25;

import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
@@ -59,6 +58,7 @@ contract pUSD is
uint8 tokenDecimals;
string tokenName;
string tokenSymbol;
uint256 version;
}

// keccak256(abi.encode(uint256(keccak256("plume.storage.pUSD")) - 1)) & ~bytes32(uint256(0xff))
@@ -73,9 +73,11 @@ contract pUSD is

// ========== EVENTS ==========
event VaultChanged(address oldVault, address newVault);
event Reinitialized(uint256 version);

// ========== ROLES ==========
bytes32 public constant VAULT_ADMIN_ROLE = keccak256("VAULT_ADMIN_ROLE");
//bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");

/**
* @notice Prevent the implementation contract from being initialized or reinitialized
@@ -103,13 +105,40 @@ contract pUSD is
revert InvalidAsset();
}

super.initialize(owner, "Plume USD", "pUSD", asset_, false, false);
__UUPSUpgradeable_init(); // Add this line
__AccessControl_init(); // Add this line
__ERC20_init("Plume USD", "pUSD");
__ReentrancyGuard_init();

super.initialize(owner, "Plume USD", "pUSD", asset_, false, false);

pUSDStorage storage $ = _getpUSDStorage();
$.vault = IVault(vault_);
$.version = 1; // Set initial version

_grantRole(VAULT_ADMIN_ROLE, owner);
_grantRole(DEFAULT_ADMIN_ROLE, owner);
_grantRole(UPGRADER_ROLE, owner); // Grant upgrader role to owner
ungaro marked this conversation as resolved.
Show resolved Hide resolved
}

function reinitialize(address owner, IERC20 asset_, address vault_) public onlyRole(UPGRADER_ROLE) {
pUSDStorage storage $ = _getpUSDStorage();

// Increment version
$.version += 1;

// Reinitialize as needed
require(owner != address(0), "Zero address owner");
require(address(asset_) != address(0), "Zero address asset");
require(vault_ != address(0), "Zero address vault");

$.vault = IVault(vault_);

_grantRole(VAULT_ADMIN_ROLE, owner);
_grantRole(DEFAULT_ADMIN_ROLE, owner);
_grantRole(UPGRADER_ROLE, owner);

emit Reinitialized($.version);
}

// ========== ADMIN FUNCTIONS ==========
@@ -125,7 +154,6 @@ contract pUSD is
revert InvalidVault();
}

ungaro marked this conversation as resolved.
Show resolved Hide resolved

// Validate teller interface support
// TODO: this should rather validate some function in the vault contract.
try ITeller(newVault).isPaused() returns (bool) { }
@@ -149,6 +177,14 @@ contract pUSD is
return address(_getpUSDStorage().vault);
}

/**
* @notice Get the current pUSD version
* @return uint256 version of the pUSD contract
*/
function version() public view returns (uint256) {
return _getpUSDStorage().version;
}

// ========== COMPONENT TOKEN INTEGRATION ==========

/**
@@ -323,4 +359,15 @@ contract pUSD is
|| super.supportsInterface(interfaceId);
eyqs marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @notice Internal function to authorize an upgrade to a new implementation
* @dev Only callable by addresses with UPGRADER_ROLE
* @param newImplementation Address of the new implementation contract
*/
function _authorizeUpgrade(
address newImplementation
) internal override(ComponentToken, UUPSUpgradeable) onlyRole(UPGRADER_ROLE) {
super._authorizeUpgrade(newImplementation); // Call ComponentToken's checks
}

}