diff --git a/src/contracts/fraxtal/fpi/FPI.sol b/src/contracts/fraxtal/fpi/FPI.sol index 843e831..a04cfe5 100644 --- a/src/contracts/fraxtal/fpi/FPI.sol +++ b/src/contracts/fraxtal/fpi/FPI.sol @@ -1,25 +1,7 @@ pragma solidity ^0.8.0; -import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; +import { ERC20PermitPermissionedNonBridgeableMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol"; -contract FPI is ERC20PermitPermissionedOptiMintable { - /// @param _creator_address The contract creator - /// @param _timelock_address The timelock - /// @param _bridge Address of the L2 standard bridge - /// @param _remoteToken Address of the corresponding L1 token - constructor( - address _creator_address, - address _timelock_address, - address _bridge, - address _remoteToken - ) - ERC20PermitPermissionedOptiMintable( - _creator_address, - _timelock_address, - _bridge, - _remoteToken, - "Frax Price Index", - "FPI" - ) - {} +contract FPI is ERC20PermitPermissionedNonBridgeableMintable { + constructor() ERC20PermitPermissionedNonBridgeableMintable("Frax Price Index", "FPI") {} } diff --git a/src/contracts/fraxtal/fpis/FPIS.sol b/src/contracts/fraxtal/fpis/FPIS.sol new file mode 100644 index 0000000..08f44f7 --- /dev/null +++ b/src/contracts/fraxtal/fpis/FPIS.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.8.0; + +import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; + +contract FPIS is ERC20PermitPermissionedOptiMintable { + /// @param _creator_address Address of the contract creator + /// @param _timelock_address Address of the timelock + /// @param _bridge Address of the L2 standard bridge + /// @param _remoteToken Address of the corresponding L1 token + constructor( + address _creator_address, + address _timelock_address, + address _bridge, + address _remoteToken + ) + ERC20PermitPermissionedOptiMintable( + _creator_address, + _timelock_address, + _bridge, + _remoteToken, + "Frax Price Index Share", + "FPIS" + ) + {} +} diff --git a/src/contracts/fraxtal/fpis/IFPI.sol b/src/contracts/fraxtal/fpis/IFPI.sol new file mode 100644 index 0000000..f288f33 --- /dev/null +++ b/src/contracts/fraxtal/fpis/IFPI.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.8.0; + +import { IERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/interfaces/IERC20PermitPermissionedOptiMintable.sol"; + +/// @title IFPIS +/// @notice Interface for the FPIS contract +interface IFPIS is IERC20PermitPermissionedOptiMintable {} diff --git a/src/contracts/fraxtal/frxBTC/FrxBTC.sol b/src/contracts/fraxtal/frxBTC/FrxBTC.sol index 92aa64f..f6bac49 100644 --- a/src/contracts/fraxtal/frxBTC/FrxBTC.sol +++ b/src/contracts/fraxtal/frxBTC/FrxBTC.sol @@ -1,25 +1,7 @@ pragma solidity ^0.8.0; -import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; +import { ERC20PermitPermissionedNonBridgeableMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol"; -contract FrxBTC is ERC20PermitPermissionedOptiMintable { - /// @param _creator_address The contract creator - /// @param _timelock_address The timelock - /// @param _bridge Address of the L2 standard bridge - /// @param _remoteToken Address of the corresponding L1 token - constructor( - address _creator_address, - address _timelock_address, - address _bridge, - address _remoteToken - ) - ERC20PermitPermissionedOptiMintable( - _creator_address, - _timelock_address, - _bridge, - _remoteToken, - "Frax Bitcoin", - "frxBTC" - ) - {} +contract FrxBTC is ERC20PermitPermissionedNonBridgeableMintable { + constructor() ERC20PermitPermissionedNonBridgeableMintable("Frax Bitcoin", "frxBTC") {} } diff --git a/src/contracts/fraxtal/frxUSD/FrxUSD.sol b/src/contracts/fraxtal/frxUSD/FrxUSD.sol index 1e09154..6d3f6c6 100644 --- a/src/contracts/fraxtal/frxUSD/FrxUSD.sol +++ b/src/contracts/fraxtal/frxUSD/FrxUSD.sol @@ -17,5 +17,5 @@ pragma solidity ^0.8.0; import { FrxUSD3 } from "src/contracts/fraxtal/frxUSD/versioning/FrxUSD3.sol"; contract FrxUSD is FrxUSD3 { - constructor(address _bridge, address _remoteToken) FrxUSD3(_bridge, _remoteToken) {} + constructor() FrxUSD3() {} } diff --git a/src/contracts/fraxtal/frxUSD/versioning/FrxUSD2.sol b/src/contracts/fraxtal/frxUSD/versioning/FrxUSD2.sol index 80671d6..ada7562 100644 --- a/src/contracts/fraxtal/frxUSD/versioning/FrxUSD2.sol +++ b/src/contracts/fraxtal/frxUSD/versioning/FrxUSD2.sol @@ -1,8 +1,8 @@ pragma solidity ^0.8.0; -import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; +import { ERC20PermitPermissionedNonBridgeableMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol"; -contract FrxUSD2 is ERC20PermitPermissionedOptiMintable { +contract FrxUSD2 is ERC20PermitPermissionedNonBridgeableMintable { /// @notice Mapping indicating which addresses are frozen mapping(address => bool) public isFrozen; @@ -17,28 +17,10 @@ contract FrxUSD2 is ERC20PermitPermissionedOptiMintable { /// @notice Upgrade version of the contract /// @dev Does not impact EIP712 version, which is automatically set to "1" in constructor function version() public pure virtual override returns (string memory) { - return "2.0.1"; + return "2.1.0"; } - /// @param _creator_address The contract creator - /// @param _timelock_address The timelock - /// @param _bridge Address of the L2 standard bridge - /// @param _remoteToken Address of the corresponding L1 token - constructor( - address _creator_address, - address _timelock_address, - address _bridge, - address _remoteToken - ) - ERC20PermitPermissionedOptiMintable( - _creator_address, - _timelock_address, - _bridge, - _remoteToken, - "Frax USD", - "frxUSD" - ) - {} + constructor() ERC20PermitPermissionedNonBridgeableMintable("Frax USD", "frxUSD") {} function addFreezer(address _freezer) external onlyOwner { if (isFreezer[_freezer]) revert AlreadyFreezer(); diff --git a/src/contracts/fraxtal/frxUSD/versioning/FrxUSD3.sol b/src/contracts/fraxtal/frxUSD/versioning/FrxUSD3.sol index 5d156a0..fe60f74 100644 --- a/src/contracts/fraxtal/frxUSD/versioning/FrxUSD3.sol +++ b/src/contracts/fraxtal/frxUSD/versioning/FrxUSD3.sol @@ -14,7 +14,7 @@ contract FrxUSD3 is FrxUSD2, EIP3009Module, PermitModule { return "3.0.0"; } - constructor(address _bridge, address _remoteToken) FrxUSD2(address(1), address(1), _bridge, _remoteToken) {} + constructor() FrxUSD2() {} /*////////////////////////////////////////////////////////////// Module Overrides diff --git a/src/contracts/fraxtal/sfrxETH/SfrxETH.sol b/src/contracts/fraxtal/sfrxETH/SfrxETH.sol index dd17ab0..8bb9f6b 100644 --- a/src/contracts/fraxtal/sfrxETH/SfrxETH.sol +++ b/src/contracts/fraxtal/sfrxETH/SfrxETH.sol @@ -1,26 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; -import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; +import { ERC20PermitPermissionedNonBridgeableMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol"; -contract SfrxETH is ERC20PermitPermissionedOptiMintable { - /// @param _creator_address The contract creator - /// @param _timelock_address The timelock - /// @param _bridge Address of the L2 standard bridge - /// @param _remoteToken Address of the corresponding L1 token - constructor( - address _creator_address, - address _timelock_address, - address _bridge, - address _remoteToken - ) - ERC20PermitPermissionedOptiMintable( - _creator_address, - _timelock_address, - _bridge, - _remoteToken, - "Staked Frax Ether", - "sfrxETH" - ) - {} +contract SfrxETH is ERC20PermitPermissionedNonBridgeableMintable { + constructor() ERC20PermitPermissionedNonBridgeableMintable("Staked Frax Ether", "sfrxETH") {} } diff --git a/src/contracts/fraxtal/sfrxUSD/SfrxUSD.sol b/src/contracts/fraxtal/sfrxUSD/SfrxUSD.sol index de9adea..733c04a 100644 --- a/src/contracts/fraxtal/sfrxUSD/SfrxUSD.sol +++ b/src/contracts/fraxtal/sfrxUSD/SfrxUSD.sol @@ -17,5 +17,5 @@ pragma solidity ^0.8.0; import { SfrxUSD2 } from "src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD2.sol"; contract SfrxUSD is SfrxUSD2 { - constructor(address _bridge, address _remoteToken) SfrxUSD2(_bridge, _remoteToken) {} + constructor() SfrxUSD2() {} } diff --git a/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD.sol b/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD.sol index 7f5f8b9..c20e29a 100644 --- a/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD.sol +++ b/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD.sol @@ -1,29 +1,11 @@ pragma solidity ^0.8.0; -import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; +import { ERC20PermitPermissionedNonBridgeableMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol"; -contract SfrxUSD is ERC20PermitPermissionedOptiMintable { +contract SfrxUSD is ERC20PermitPermissionedNonBridgeableMintable { function version() public pure virtual override returns (string memory) { - return "1.0.0"; + return "1.1.0"; } - /// @param _creator_address The contract creator - /// @param _timelock_address The timelock - /// @param _bridge Address of the L2 standard bridge - /// @param _remoteToken Address of the corresponding L1 token - constructor( - address _creator_address, - address _timelock_address, - address _bridge, - address _remoteToken - ) - ERC20PermitPermissionedOptiMintable( - _creator_address, - _timelock_address, - _bridge, - _remoteToken, - "Staked Frax USD", - "sfrxUSD" - ) - {} + constructor() ERC20PermitPermissionedNonBridgeableMintable("Staked Frax USD", "sfrxUSD") {} } diff --git a/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD2.sol b/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD2.sol index 9ac63de..bed30a2 100644 --- a/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD2.sol +++ b/src/contracts/fraxtal/sfrxUSD/versioning/SfrxUSD2.sol @@ -11,10 +11,10 @@ import { EIP3009Module, SignatureModule } from "src/contracts/shared/core/module /// @dev v3.0.0 adds ERC-1271 and EIP-3009 support contract SfrxUSD2 is SfrxUSD, EIP3009Module, PermitModule { function version() public pure override returns (string memory) { - return "2.0.0"; + return "2.0.1"; } - constructor(address _bridge, address _remoteToken) SfrxUSD(address(1), address(1), _bridge, _remoteToken) {} + constructor() SfrxUSD() {} /*////////////////////////////////////////////////////////////// Module Overrides diff --git a/src/contracts/fraxtal/shared/ERC20ExWrappedPPOM.sol b/src/contracts/fraxtal/shared/ERC20ExWrappedPPOM.sol index bdbee16..82ba1ca 100644 --- a/src/contracts/fraxtal/shared/ERC20ExWrappedPPOM.sol +++ b/src/contracts/fraxtal/shared/ERC20ExWrappedPPOM.sol @@ -107,111 +107,15 @@ contract ERC20ExWrappedPPOM is // ISemver // ======================================= - /// @custom:semver 1.0.0 - string public version = "1.0.0"; + /// @custom:semver 1.1.0 + string public version = "1.1.0"; /* ========== CONSTRUCTOR ========== */ - // /// @custom:semver 1.0.0 - // /// @param _creator_address The contract creator - // /// @param _timelock_address The timelock - // /// @param _bridge Address of the L2 standard bridge - // /// @param _remoteToken Address of the corresponding L1 token - // /// @param _name ERC20 name - // /// @param _symbol ERC20 symbol - // constructor( - // address _creator_address, - // address _timelock_address, - // address _bridge, - // address _remoteToken, - // string memory _name, - // string memory _symbol - // ) EIP712StoragePad(_name) ERC20ReorderedState(_name, _symbol) OwnedV2(_creator_address) { - // REMOTE_TOKEN = _remoteToken; - // BRIDGE = _bridge; - // timelock_address = _timelock_address; - // } - - constructor() ERC20ReorderedState("Dummy Token", "DUMMY") OwnedV2(msg.sender) { + constructor() ERC20ReorderedState("Dummy Token", "DUMMY") OwnedV2(address(1)) { _disableInitializers(); } - /// @notice Initializer. - /// @param _timelock_address The timelock - /// @param _bridge Address of the L2 standard bridge - /// @param _remoteToken Address of the corresponding L1 token - /// @param _initTotalSupply The totalSupply - /// @param _nameIn ERC20 name - /// @param _symbolIn ERC20 symbol - /// @param _versionIn Version - function initialize( - address _creator_address, - address _timelock_address, - address _bridge, - address _remoteToken, - uint256 _initTotalSupply, - string memory _nameIn, - string memory _symbolIn, - string memory _versionIn - ) public initializer { - // Set version - version = _versionIn; - - // Overwrite _totalSupply storage - //-------------------------------------- - assembly { - sstore(9, _initTotalSupply) - } - - // Overwrite ERC20 _name and _symbol storage - //-------------------------------------- - // Make sure _nameIn and _symbolIn are below 31 bytes - uint256 _nameLength = bytes(_nameIn).length; - uint256 _symbolLength = bytes(_symbolIn).length; - if ((_nameLength >= 32) || (_symbolLength >= 32)) { - revert("Name and/or symbol must be lt 32 bytes"); - } - - // Write to the storage slots - // https://ethereum.stackexchange.com/questions/126269/how-to-store-and-retrieve-string-which-is-more-than-32-bytesor-could-be-less-th - assembly { - // If string length <= 31 we store a short array - // length storage variable layout : - // bytes 0 - 31 : string data - // byte 32 : length * 2 - // data storage variable is UNUSED in this case - sstore(4, or(mload(add(_nameIn, 0x20)), mul(_nameLength, 2))) - sstore(5, or(mload(add(_symbolIn, 0x20)), mul(_symbolLength, 2))) - } - - // Set EIP712 variables - //-------------------------------------- - _SStrName = _nameIn.toShortStringWithFallback(_nameFallback); - _SStrVersion = _versionIn.toShortStringWithFallback(_versionFallback); - _hashedName = keccak256(bytes(_nameIn)); - _hashedVersion = keccak256(bytes(_versionIn)); - _cachedChainId = block.chainid; - _cachedDomainSeparator = _buildDomainSeparator(); - _cachedThis = address(this); - - // Set owner and timelock - //-------------------------------------- - owner = _creator_address; - timelock_address = _timelock_address; - - // Set BRIDGE and REMOTE_TOKEN - //-------------------------------------- - REMOTE_TOKEN = _remoteToken; - BRIDGE = _bridge; - - // Move existing gas tokens to the _creator_address - //-------------------------------------- - (bool success, ) = _creator_address.call{ value: address(this).balance }(""); - if (!success) { - revert TransferFailed(); - } - } - /* ========== MODIFIERS ========== */ /// @notice A modifier that only allows the contract owner or the timelock to call @@ -277,25 +181,15 @@ contract ERC20ExWrappedPPOM is /* ========== RESTRICTED FUNCTIONS [BRIDGE] ========== */ /// @notice Allows the StandardBridge on this network to mint tokens. - /// @param _to Address to mint tokens to. - /// @param _amount Amount of tokens to mint. - function mint( - address _to, - uint256 _amount - ) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyBridge { - _mint(_to, _amount); - emit Mint(_to, _amount); + /// @dev Deprecated in v1.1.0 + function mint(address, uint256) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) { + revert Deprecated(); } /// @notice Allows the StandardBridge on this network to burn tokens. No approval needed - /// @param _from Address to burn tokens from. - /// @param _amount Amount of tokens to burn. - function burn( - address _from, - uint256 _amount - ) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyBridge { - _burn(_from, _amount); - emit Burn(_from, _amount); + /// @dev Deprecated in v1.1.0 + function burn(address, uint256) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) { + revert Deprecated(); } /* ========== RESTRICTED FUNCTIONS [NON-BRIDGE MINTERS] ========== */ @@ -518,16 +412,6 @@ contract ERC20ExWrappedPPOM is /* ========== EVENTS ========== */ - /// @notice Emitted whenever the bridge burns tokens from an account - /// @param account Address of the account tokens are being burned from - /// @param amount Amount of tokens burned - event Burn(address indexed account, uint256 amount); - - /// @notice Emitted whenever the bridge mints tokens to an account - /// @param account Address of the account tokens are being minted for - /// @param amount Amount of tokens minted. - event Mint(address indexed account, uint256 amount); - /// @notice Emitted when a non-bridge minter is added /// @param minter_address Address of the new minter event MinterAdded(address minter_address); @@ -552,6 +436,6 @@ contract ERC20ExWrappedPPOM is /// @param amount Amount of tokens minted event TokenMinterMinted(address indexed from, address indexed to, uint256 amount); - /// @notice Error for when the gas token withdrawal in the initializer fails - error TransferFailed(); + /// @notice Error for deprecated functions + error Deprecated(); } diff --git a/src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol b/src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol new file mode 100644 index 0000000..86faf6a --- /dev/null +++ b/src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ERC20PermitPermissionedOptiMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedOptiMintable.sol"; + +/// @title ERC20PermitPermissionedNonBridgeableMintable +/// @notice A native ERC20 token that cannot be bridged via the native bridge +contract ERC20PermitPermissionedNonBridgeableMintable is ERC20PermitPermissionedOptiMintable { + /// @custom:semver 1.0.0 + function version() public pure virtual override returns (string memory) { + return "1.0.0"; + } + + constructor( + string memory _name, + string memory _symbol + ) ERC20PermitPermissionedOptiMintable(address(1), address(0), address(0), address(0), _name, _symbol) {} + + function mint(address, uint256) external pure override { + revert Deprecated(); + } + + function burn(address, uint256) external pure override { + revert Deprecated(); + } + + error Deprecated(); +} diff --git a/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.json b/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.json new file mode 100644 index 0000000..c910109 --- /dev/null +++ b/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.json @@ -0,0 +1,47 @@ +{ + "chainId": 252, + "createdAt": 1764702807000, + "meta": { + "description": "", + "name": "Transactions Batch" + }, + "transactions": [ + { + "data": "0x9623609d000000000000000000000000fc000000000000000000000000000000000000010000000000000000000000006550284ea5dcb134a45a6f3c80afa2b30bc56fe90000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000418160ddd00000000000000000000000000000000000000000000000000000000", + "operation": 0, + "to": "0xfC0000000000000000000000000000000000000a", + "value": "0" + }, + { + "data": "0x9623609d000000000000000000000000fc00000000000000000000000000000000000008000000000000000000000000e8cd13de17cec6fcd9dd5e0a1465da240f9515360000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000418160ddd00000000000000000000000000000000000000000000000000000000", + "operation": 0, + "to": "0xfC0000000000000000000000000000000000000a", + "value": "0" + }, + { + "data": "0x9623609d000000000000000000000000fc00000000000000000000000000000000000003000000000000000000000000dc3369c18ff9c077b803c98b6260a186ade9a4260000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000418160ddd00000000000000000000000000000000000000000000000000000000", + "operation": 0, + "to": "0xfC0000000000000000000000000000000000000a", + "value": "0" + }, + { + "data": "0x9623609d000000000000000000000000fc0000000000000000000000000000000000000700000000000000000000000013ee9ace05a91360f847f36ee22729336725a1de0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000418160ddd00000000000000000000000000000000000000000000000000000000", + "operation": 0, + "to": "0xfC0000000000000000000000000000000000000a", + "value": "0" + }, + { + "data": "0x9623609d000000000000000000000000fc0000000000000000000000000000000000000600000000000000000000000056fdaa8ea2fd7ee7a93a15cf8c49a9d3307392ba0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000418160ddd00000000000000000000000000000000000000000000000000000000", + "operation": 0, + "to": "0xfC0000000000000000000000000000000000000a", + "value": "0" + }, + { + "data": "0x9623609d000000000000000000000000fc00000000000000000000000000000000000005000000000000000000000000d3e09b109c90d98c0afc09ff961f299b2bffb9fe0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000418160ddd00000000000000000000000000000000000000000000000000000000", + "operation": 0, + "to": "0xfC0000000000000000000000000000000000000a", + "value": "0" + } + ], + "version": "1.0" +} diff --git a/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.s.sol b/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.s.sol new file mode 100644 index 0000000..7c42f20 --- /dev/null +++ b/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.s.sol @@ -0,0 +1,143 @@ +pragma solidity ^0.8.0; + +import { BaseScript } from "frax-std/BaseScript.sol"; +import { ERC1967Utils } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; +import { ProxyAdmin, ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import { console } from "forge-std/console.sol"; + +import { FrxUSD } from "src/contracts/fraxtal/frxUSD/FrxUSD.sol"; +import { SfrxUSD } from "src/contracts/fraxtal/sfrxUSD/SfrxUSD.sol"; +import { FPI } from "src/contracts/fraxtal/fpi/FPI.sol"; +import { FrxBTC } from "src/contracts/fraxtal/frxBTC/FrxBTC.sol"; +import { FrxETH } from "src/contracts/fraxtal/frxETH/FrxETH.sol"; +import { SfrxETH } from "src/contracts/fraxtal/sfrxETH/SfrxETH.sol"; + +import { SafeTx, SafeTxHelper } from "frax-std/SafeTxHelper.sol"; + +address constant FRXUSD_PROXY = 0xFc00000000000000000000000000000000000001; +address constant SFRXUSD_PROXY = 0xfc00000000000000000000000000000000000008; +address constant FPI_PROXY = 0xFc00000000000000000000000000000000000003; +address constant FRXBTC_PROXY = 0xfC00000000000000000000000000000000000007; +address constant FRXETH_PROXY = 0xFC00000000000000000000000000000000000006; +address constant SFRXETH_PROXY = 0xFC00000000000000000000000000000000000005; + +// forge script src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.s.sol --rpc-url https://rpc.frax.com TODO: verify +contract DeprecateNativeBridging is BaseScript { + address public proxyAdmin; + address public owner; + address public implementation; + SafeTx[] public txs; + SafeTxHelper public txHelper; + + bool public isTest = false; + + function setUp() public override { + bytes32 adminSlot = vm.load(FRXUSD_PROXY, ERC1967Utils.ADMIN_SLOT); + proxyAdmin = address(uint160(uint256(adminSlot))); + owner = ProxyAdmin(proxyAdmin).owner(); + + txHelper = new SafeTxHelper(); + + super.setUp(); + } + + function run() public { + deployAndUpgradeFrxUsd(); + deployAndUpgradeSfrxUsd(); + deployAndUpgradeFpi(); + deployAndUpgradeFrxBtc(); + deployAndUpgradeFrxEth(); + deployAndUpgradeSfrxEth(); + + if (!isTest) generateMsigTx(); + } + + function runTest() public { + isTest = true; + run(); + } + + function deployAndUpgradeFrxUsd() public { + vm.startBroadcast(deployer); + implementation = address(new FrxUSD()); + require(implementation != address(0), "Failed implementation"); + vm.stopBroadcast(); + + upgrade(FRXUSD_PROXY); + } + + function deployAndUpgradeSfrxUsd() public { + vm.startBroadcast(deployer); + implementation = address(new SfrxUSD()); + require(implementation != address(0), "Failed implementation"); + vm.stopBroadcast(); + + upgrade(SFRXUSD_PROXY); + } + + function deployAndUpgradeFpi() public { + vm.startBroadcast(deployer); + implementation = address(new FPI()); + require(implementation != address(0), "Failed implementation"); + vm.stopBroadcast(); + + upgrade(FPI_PROXY); + } + + function deployAndUpgradeFrxBtc() public { + vm.startBroadcast(deployer); + implementation = address(new FrxBTC()); + require(implementation != address(0), "Failed implementation"); + vm.stopBroadcast(); + + upgrade(FRXBTC_PROXY); + } + + function deployAndUpgradeFrxEth() public { + vm.startBroadcast(deployer); + implementation = address(new FrxETH()); + require(implementation != address(0), "Failed implementation"); + vm.stopBroadcast(); + + upgrade(FRXETH_PROXY); + } + + function deployAndUpgradeSfrxEth() public { + vm.startBroadcast(deployer); + implementation = address(new SfrxETH()); + require(implementation != address(0), "Failed implementation"); + vm.stopBroadcast(); + + upgrade(SFRXETH_PROXY); + } + + function upgrade(address proxy) public { + string memory symbolBefore = IERC20Metadata(proxy).symbol(); + + bytes memory initializeData = abi.encodeWithSignature("totalSupply()"); + bytes memory upgradeData = abi.encodeCall( + ProxyAdmin.upgradeAndCall, + (ITransparentUpgradeableProxy(payable(proxy)), implementation, initializeData) + ); + vm.prank(owner); + (bool success, ) = proxyAdmin.call(upgradeData); + require(success, "Upgrade failed"); + + txs.push(SafeTx({ name: "upgrade", to: proxyAdmin, value: 0, data: upgradeData })); + + string memory symbolAfter = IERC20Metadata(proxy).symbol(); + require(keccak256(bytes(symbolBefore)) == keccak256(bytes(symbolAfter)), "Symbol changed"); + } + + function generateMsigTx() public { + string memory root = vm.projectRoot(); + string memory filename = string.concat( + root, + "/src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.json" + ); + txHelper.writeTxs(txs, filename); + + console.log("Deploy msig tx from %s", owner); + } +} diff --git a/src/script/fraxtal/frxUSD/DeployFrxUSD.s.sol b/src/script/fraxtal/frxUSD/DeployFrxUSD.s.sol index a98e17d..ac09e07 100644 --- a/src/script/fraxtal/frxUSD/DeployFrxUSD.s.sol +++ b/src/script/fraxtal/frxUSD/DeployFrxUSD.s.sol @@ -40,12 +40,7 @@ contract DeployFrxUSD is BaseScript { } function deployFrxUsd() public broadcaster { - implementation = address( - new FrxUSD( - address(0x4200000000000000000000000000000000000010), - address(0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29) - ) - ); + implementation = address(new FrxUSD()); require(implementation != address(0), "Failed implementation"); } diff --git a/src/script/fraxtal/sfrxUSD/DeploySfrxUSD.s.sol b/src/script/fraxtal/sfrxUSD/DeploySfrxUSD.s.sol index 2546e50..b028ed8 100644 --- a/src/script/fraxtal/sfrxUSD/DeploySfrxUSD.s.sol +++ b/src/script/fraxtal/sfrxUSD/DeploySfrxUSD.s.sol @@ -40,12 +40,7 @@ contract DeploySfrxUSD is BaseScript { } function deployFrxUsd() public broadcaster { - implementation = address( - new SfrxUSD( - address(0x4200000000000000000000000000000000000010), - address(0xcf62F905562626CfcDD2261162a51fd02Fc9c5b6) - ) - ); + implementation = address(new SfrxUSD()); require(implementation != address(0), "Failed implementation"); } diff --git a/src/test/2025-12-02-deprecate-native-bridging/TestDeprecateNativeBridging.t.sol b/src/test/2025-12-02-deprecate-native-bridging/TestDeprecateNativeBridging.t.sol new file mode 100644 index 0000000..00bf08b --- /dev/null +++ b/src/test/2025-12-02-deprecate-native-bridging/TestDeprecateNativeBridging.t.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.8.0; + +import "src/script/fraxtal/2025-12-02-deprecate-native-bridging/DeprecateNativeBridging.s.sol"; +import "frax-std/FraxTest.sol"; +import { ERC20PermitPermissionedNonBridgeableMintable } from "src/contracts/fraxtal/shared/ERC20PermitPermissionedNonBridgeableMintable.sol"; + +contract TestDeprecateNativeBridging is FraxTest { + DeprecateNativeBridging public script; + + function setUp() public { + vm.createSelectFork("https://rpc.frax.com", 28_000_000); + + script = new DeprecateNativeBridging(); + script.setUp(); + script.runTest(); + } + + function test_CannotBridgeNative() public { + assertBridgeReverted(FRXUSD_PROXY); + assertBridgeReverted(SFRXUSD_PROXY); + assertBridgeReverted(FPI_PROXY); + assertBridgeReverted(FRXBTC_PROXY); + assertBridgeReverted(FRXETH_PROXY); + assertBridgeReverted(SFRXETH_PROXY); + } + + function assertBridgeReverted(address token) internal { + vm.expectRevert(ERC20PermitPermissionedNonBridgeableMintable.Deprecated.selector); + ERC20PermitPermissionedNonBridgeableMintable(token).mint(address(1), 1 ether); + + vm.expectRevert(ERC20PermitPermissionedNonBridgeableMintable.Deprecated.selector); + ERC20PermitPermissionedNonBridgeableMintable(token).burn(address(1), 1 ether); + } +} diff --git a/src/test/FrxUSD/Fraxtal/CompilanceTests.t.sol b/src/test/FrxUSD/Fraxtal/CompilanceTests.t.sol index eca21e6..dd6c555 100644 --- a/src/test/FrxUSD/Fraxtal/CompilanceTests.t.sol +++ b/src/test/FrxUSD/Fraxtal/CompilanceTests.t.sol @@ -29,10 +29,7 @@ contract FrxUSD_Fraxtal_Compliance is FraxTest { /// @notice needed to register under coverage report // implV2 = FrxUSD(deployFrxUsdImplementationFraxtal()); // implV2 = FrxUSD(0x00000000cd6f03dd0A6389C40c263838636c2C01); - implV2 = new FrxUSD( - address(0x4200000000000000000000000000000000000010), - address(0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29) - ); + implV2 = new FrxUSD(); deal(address(frxusd), al, 5000e18); deal(address(frxusd), bob, 15e18); deal(address(frxusd), carl, 69e18);