diff --git a/.prettierignore b/.prettierignore index d85a8b5..daf5db6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,3 +17,4 @@ package-lock.json pnpm-lock.yaml yarn.lock deployments +.claude diff --git a/bun.lockb b/bun.lockb index d047fc1..90390e6 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/contracts/sPRL/sPRL1.sol b/contracts/sPRL/sPRL1.sol index 6838e79..b315ca2 100644 --- a/contracts/sPRL/sPRL1.sol +++ b/contracts/sPRL/sPRL1.sol @@ -32,13 +32,7 @@ contract sPRL1 is TimeLockPenaltyERC20 { uint64 _timeLockDuration ) TimeLockPenaltyERC20( - NAME, - SYMBOL, - _underlying, - _feeReceiver, - _accessManager, - _startPenaltyPercentage, - _timeLockDuration + NAME, SYMBOL, _underlying, _feeReceiver, _accessManager, _startPenaltyPercentage, _timeLockDuration ) { } @@ -71,8 +65,9 @@ contract sPRL1 is TimeLockPenaltyERC20 { nonReentrant { // @dev using try catch to avoid reverting the transaction in case of front-running - try IERC20Permit(address(underlying)).permit(msg.sender, address(this), _assetAmount, _deadline, _v, _r, _s) { - } catch { } + try IERC20Permit(address(underlying)) + .permit(msg.sender, address(this), _assetAmount, _deadline, _v, _r, _s) { } + catch { } underlying.safeTransferFrom(msg.sender, address(this), _assetAmount); _deposit(_assetAmount); } diff --git a/contracts/sPRL/sPRL2.sol b/contracts/sPRL/sPRL2.sol index b40f285..dcb19d5 100644 --- a/contracts/sPRL/sPRL2.sol +++ b/contracts/sPRL/sPRL2.sol @@ -24,7 +24,7 @@ contract sPRL2 is TimeLockPenaltyERC20 { string constant SYMBOL = "sPRL2"; /// @dev Aura Pool PID is hardcoded and must be updated before deploying - uint256 public constant AURA_POOL_PID = 244; + uint256 public constant AURA_POOL_PID = 258; //------------------------------------------- // Storage @@ -117,13 +117,7 @@ contract sPRL2 is TimeLockPenaltyERC20 { BPTConfigParams memory _configParams ) TimeLockPenaltyERC20( - NAME, - SYMBOL, - _stakedAuraBPT, - _feeReceiver, - _accessManager, - _startPenaltyPercentage, - _timeLockDuration + NAME, SYMBOL, _stakedAuraBPT, _feeReceiver, _accessManager, _startPenaltyPercentage, _timeLockDuration ) { if (_configParams.rewardTokens.length == 0) { diff --git a/deploy/config/arbiSepolia/config.json b/deploy/config/base/arbiSepolia/config.json similarity index 82% rename from deploy/config/arbiSepolia/config.json rename to deploy/config/base/arbiSepolia/config.json index 27fe1db..4552ebc 100644 --- a/deploy/config/arbiSepolia/config.json +++ b/deploy/config/base/arbiSepolia/config.json @@ -2,11 +2,10 @@ "isMainChainFeeDistributor": false, "accessManager": "0xE2A0FA5A1e7315e6b89b12Ace2541A6a0d3E5370", "wallets": { - "dao": "0x3676b6ed4ae0c9ce3E0034510719fdF5fd585d55" + "dao": "0x66CcEC236bbcE5f1bBd1b2fC0a4014e57A55ad02" }, "tokens": { "prl": "0x0F4DE51EF1E7611aD0A9181F2d62B9c8408EFfa2", - "paUSD": "0x0000000000000000000000000000000000000000", "par": "0x78C48A7d7Fc69735fDab448fe6068bbA44a920E6", "weth": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" }, @@ -30,8 +29,8 @@ "feeReceiver": "dao", "startPenaltyPercentage": "1000000000000000000", "timeLockDuration": 86400000, - "balancerV3Vault": "0x0000000000000000000000000000000000000000", - "auraVault": "0x0000000000000000000000000000000000000000", + "balancerV3Router": "0x0000000000000000000000000000000000000000", + "auraRewardsPool": "0x0000000000000000000000000000000000000000", "auraBoosterLite": "0x0000000000000000000000000000000000000000", "auraBPT": "0x0000000000000000000000000000000000000000", "balancerBPT": "0x0000000000000000000000000000000000000000" diff --git a/deploy/config/base/config.json b/deploy/config/base/config.json new file mode 100644 index 0000000..1f78628 --- /dev/null +++ b/deploy/config/base/config.json @@ -0,0 +1,40 @@ +{ + "isMainChainFeeDistributor": false, + "accessManager": "0x0e4e7Ca9D7b1e6293D0713EFEfB4BCA010DeBF46", + "wallets": { + "dao": "0xC5201FFE258a95Af986E7cD1fcaD54f3f63f2C95" + }, + "tokens": { + "prl": "0xfD28f108e95f4D41daAE9dbfFf707D677985998E", + "par": "0x0000000000000000000000000000000000000000", + "weth": "0x0000000000000000000000000000000000000000" + }, + "rewardMerkleDistributor": { + "token": "par", + "expiredRewardsRecipient": "dao" + }, + "feeDistributor": { + "mainChain": "polygon", + "destinationReceiver": "0x0000000000000000000000000000000000000000", + "feeToken": "par", + "bridgeableToken": "0x0000000000000000000000000000000000000000" + }, + "sprl1": { + "underlying": "prl", + "feeReceiver": "dao", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200 + }, + "sprl2": { + "feeReceiver": "dao", + "permit2": "0x0000000000000000000000000000000000000000", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200, + "balancerV3Router": "0x0000000000000000000000000000000000000000", + "auraRewardsPool": "0x0000000000000000000000000000000000000000", + "auraBoosterLite": "0x0000000000000000000000000000000000000000", + "auraBPT": "0x0000000000000000000000000000000000000000", + "balancerBPT": "0x0000000000000000000000000000000000000000", + "rewardsTokens": [] + } +} diff --git a/deploy/config/mainnet/config.json b/deploy/config/mainnet/config.json new file mode 100644 index 0000000..c94ef9b --- /dev/null +++ b/deploy/config/mainnet/config.json @@ -0,0 +1,40 @@ +{ + "isMainChainFeeDistributor": false, + "accessManager": "0x94Ea8800444017695345156319e96bdB1E355F7a", + "wallets": { + "dao": "0x25Fc7ffa8f9da3582a36633d04804F0004706F9b" + }, + "tokens": { + "prl": "0x6c0aeceeDc55c9d55d8B99216a670D85330941c3", + "par": "0x68037790a0229e9ce6eaa8a99ea92964106c4703", + "weth": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + }, + "rewardMerkleDistributor": { + "token": "par", + "expiredRewardsRecipient": "dao" + }, + "feeDistributor": { + "mainChain": "polygon", + "destinationReceiver": "0x90337e484B1Cb02132fc150d3Afa262147348545", + "feeToken": "par", + "bridgeableToken": "0x74e3f9D724Da6D7e4db8EcAb4f18e6ba44f60e30" + }, + "sprl1": { + "underlying": "prl", + "feeReceiver": "dao", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200 + }, + "sprl2": { + "feeReceiver": "dao", + "permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 60, + "balancerV3Router": "0x5C6fb490BDFD3246EB0bB062c168DeCAF4bD9FDd", + "auraRewardsPool": "0x486Be73794Ec19f3e9cF57f06f03fDCf7F0A9da4", + "auraBoosterLite": "0xA57b8d98dAE62B26Ec3bcC4a365338157060B234", + "auraBPT": "0x486Be73794Ec19f3e9cF57f06f03fDCf7F0A9da4", + "balancerBPT": "0x1846C6cBE0D433e152fA358e5fF27968E18bcE7c", + "rewardsTokens": ["0xba100000625a3754423978a60c9317c58a424e3d", "0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF"] + } +} diff --git a/deploy/config/polygon/config.json b/deploy/config/polygon/config.json new file mode 100644 index 0000000..456dcc8 --- /dev/null +++ b/deploy/config/polygon/config.json @@ -0,0 +1,40 @@ +{ + "isMainChainFeeDistributor": true, + "accessManager": "0x7Df74BBB6F82eC1BCB1562a30ef5Bf5c326e2811", + "wallets": { + "dao": "0x2046c0416A558C40cb112E5ebB0Ca764c3C5c32a" + }, + "tokens": { + "prl": "0x7790dd69aa10eD3f1271E41CD7222D2a7d2D5948", + "par": "0xE2Aa7db6dA1dAE97C5f5C6914d285fBfCC32A128", + "weth": "0x0000000000000000000000000000000000000000" + }, + "rewardMerkleDistributor": { + "token": "par", + "expiredRewardsRecipient": "dao" + }, + "feeDistributor": { + "mainChain": "polygon", + "destinationReceiver": "0x0000000000000000000000000000000000000000", + "feeToken": "par", + "bridgeableToken": "0xE462Df8d4Aa7Db3aeCfe810ec8D1fa4f716BC9a8" + }, + "sprl1": { + "underlying": "prl", + "feeReceiver": "dao", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200 + }, + "sprl2": { + "feeReceiver": "dao", + "permit2": "0x0000000000000000000000000000000000000000", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200, + "balancerV3Router": "0x0000000000000000000000000000000000000000", + "auraRewardsPool": "0x0000000000000000000000000000000000000000", + "auraBoosterLite": "0x0000000000000000000000000000000000000000", + "auraBPT": "0x0000000000000000000000000000000000000000", + "balancerBPT": "0x0000000000000000000000000000000000000000", + "rewardsTokens": [] + } +} diff --git a/deploy/config/sepolia/config.json b/deploy/config/sepolia/config.json index 508f4d0..7a3c1cd 100644 --- a/deploy/config/sepolia/config.json +++ b/deploy/config/sepolia/config.json @@ -1,12 +1,11 @@ { "isMainChainFeeDistributor": true, - "accessManager": "0xe29F44Aa83EB42BA823719EA1D2d84861f72A5D0", + "accessManager": "0xfD28f108e95f4D41daAE9dbfFf707D677985998E", "wallets": { - "dao": "0x3676b6ed4ae0c9ce3E0034510719fdF5fd585d55" + "dao": "0x66CcEC236bbcE5f1bBd1b2fC0a4014e57A55ad02" }, "tokens": { "prl": "0xfaD382eE9B8229fb9B05DF9F9391baC5DD81f346", - "paUSD": "0x0000000000000000000000000000000000000000", "par": "0x68E88c802F146eAD2f99F3A91Fb880D1A2509672", "weth": "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9" }, @@ -30,9 +29,8 @@ "feeReceiver": "dao", "startPenaltyPercentage": "1000000000000000000", "timeLockDuration": 2419200, - "balancerV3Vault": "0x0000000000000000000000000000000000000000", - "auraVault": "0x0000000000000000000000000000000000000000", - "auraVaultRewardToken": "0x0000000000000000000000000000000000000000", + "balancerV3Router": "0x0000000000000000000000000000000000000000", + "auraRewardsPool": "0x0000000000000000000000000000000000000000", "auraBoosterLite": "0x0000000000000000000000000000000000000000", "auraBPT": "0x0000000000000000000000000000000000000000", "balancerBPT": "0x0000000000000000000000000000000000000000" diff --git a/deploy/config/sonic/config.json b/deploy/config/sonic/config.json new file mode 100644 index 0000000..9b510d8 --- /dev/null +++ b/deploy/config/sonic/config.json @@ -0,0 +1,40 @@ +{ + "isMainChainFeeDistributor": false, + "accessManager": "0x8eFb3DED78FbaEF2a4eFe01E01BBD911E4094b78", + "wallets": { + "dao": "0xC5201FFE258a95Af986E7cD1fcaD54f3f63f2C95" + }, + "tokens": { + "prl": "0xfD28f108e95f4D41daAE9dbfFf707D677985998E", + "par": "0x0000000000000000000000000000000000000000", + "weth": "0x0000000000000000000000000000000000000000" + }, + "rewardMerkleDistributor": { + "token": "par", + "expiredRewardsRecipient": "dao" + }, + "feeDistributor": { + "mainChain": "polygon", + "destinationReceiver": "0x0000000000000000000000000000000000000000", + "feeToken": "par", + "bridgeableToken": "0x0000000000000000000000000000000000000000" + }, + "sprl1": { + "underlying": "prl", + "feeReceiver": "dao", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200 + }, + "sprl2": { + "feeReceiver": "dao", + "permit2": "0x0000000000000000000000000000000000000000", + "startPenaltyPercentage": "500000000000000000", + "timeLockDuration": 2419200, + "balancerV3Router": "0x0000000000000000000000000000000000000000", + "auraRewardsPool": "0x0000000000000000000000000000000000000000", + "auraBoosterLite": "0x0000000000000000000000000000000000000000", + "auraBPT": "0x0000000000000000000000000000000000000000", + "balancerBPT": "0x0000000000000000000000000000000000000000", + "rewardsTokens": [] + } +} diff --git a/deploy/scripts/fees/MainFeeDistributor.ts b/deploy/scripts/fees/MainFeeDistributor.ts index cc0cf3e..c6fea49 100644 --- a/deploy/scripts/fees/MainFeeDistributor.ts +++ b/deploy/scripts/fees/MainFeeDistributor.ts @@ -1,9 +1,8 @@ import assert from "assert"; -import { ethers } from "ethers"; import { type DeployFunction } from "hardhat-deploy/types"; -import { checkAddressValid, GAS, getTokenAddressFromConfig, isAddressValid } from "../../utils"; +import { checkAddressValid, getTokenAddressFromConfig } from "../../utils"; import { readFileSync } from "fs"; import { ConfigData } from "../../utils/types"; @@ -34,7 +33,6 @@ const deploy: DeployFunction = async (hre) => { args: [accessManager, bridgeableToken, feeToken], log: true, skipIfAlreadyDeployed: false, - ...GAS, }); console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${contract.address}`); diff --git a/deploy/scripts/fees/SideChainFeeCollector.ts b/deploy/scripts/fees/SideChainFeeCollector.ts index 8508d2e..71f842b 100644 --- a/deploy/scripts/fees/SideChainFeeCollector.ts +++ b/deploy/scripts/fees/SideChainFeeCollector.ts @@ -1,9 +1,8 @@ import assert from "assert"; -import { ethers } from "ethers"; import { type DeployFunction } from "hardhat-deploy/types"; -import { checkAddressValid, GAS, getLzEidReceiver, getTokenAddressFromConfig, isAddressValid } from "../../utils"; +import { checkAddressValid, getLzEidReceiver, getTokenAddressFromConfig } from "../../utils"; import { readFileSync } from "fs"; import { ConfigData } from "../../utils/types"; @@ -36,7 +35,6 @@ const deploy: DeployFunction = async (hre) => { args: [accessManager, lzEidReceiver, bridgeableToken, destinationReceiver, feeToken], log: true, skipIfAlreadyDeployed: false, - ...GAS, }); console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${contract.address}`); diff --git a/deploy/scripts/rewardMerkleDistributor/RewardMerkleDistributor.ts b/deploy/scripts/rewardMerkleDistributor/RewardMerkleDistributor.ts index 1faaaf7..79ac598 100644 --- a/deploy/scripts/rewardMerkleDistributor/RewardMerkleDistributor.ts +++ b/deploy/scripts/rewardMerkleDistributor/RewardMerkleDistributor.ts @@ -2,7 +2,7 @@ import assert from "assert"; import { type DeployFunction } from "hardhat-deploy/types"; -import { checkAddressValid, GAS, getTokenAddressFromConfig, getWalletAddressFromConfig } from "../../utils"; +import { checkAddressValid, getTokenAddressFromConfig, getWalletAddressFromConfig } from "../../utils"; import { readFileSync } from "fs"; import { ConfigData } from "../../utils/types"; @@ -37,7 +37,6 @@ const deploy: DeployFunction = async (hre) => { args: [accessManager, token, expiredRewardsRecipient], log: true, skipIfAlreadyDeployed: false, - ...GAS, }); console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${contract.address}`); diff --git a/deploy/scripts/sprl/sPRL1.ts b/deploy/scripts/sprl/sPRL1.ts index 12124c1..3b70243 100644 --- a/deploy/scripts/sprl/sPRL1.ts +++ b/deploy/scripts/sprl/sPRL1.ts @@ -1,9 +1,8 @@ import assert from "assert"; -import { ethers } from "ethers"; import { type DeployFunction } from "hardhat-deploy/types"; -import { GAS, getTokenAddressFromConfig, getWalletAddressFromConfig, isAddressValid } from "../../utils"; +import { getTokenAddressFromConfig, getWalletAddressFromConfig, isAddressValid } from "../../utils"; import { readFileSync } from "fs"; import { ConfigData } from "../../utils/types"; @@ -33,7 +32,6 @@ const deploy: DeployFunction = async (hre) => { args: [underlying, feeReceiver, accessManager, sprl1Data.startPenaltyPercentage, sprl1Data.timeLockDuration], log: true, skipIfAlreadyDeployed: false, - ...GAS, }); console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${contract.address}`); diff --git a/deploy/scripts/sprl/sPRL2.ts b/deploy/scripts/sprl/sPRL2.ts index 5c45610..0352088 100644 --- a/deploy/scripts/sprl/sPRL2.ts +++ b/deploy/scripts/sprl/sPRL2.ts @@ -1,15 +1,8 @@ import assert from "assert"; -import { ethers } from "ethers"; import { type DeployFunction } from "hardhat-deploy/types"; -import { - checkAddressValid, - GAS, - getTokenAddressFromConfig, - getWalletAddressFromConfig, - isAddressValid, -} from "../../utils"; +import { checkAddressValid, getTokenAddressFromConfig, getWalletAddressFromConfig, isAddressValid } from "../../utils"; import { readFileSync } from "fs"; import { ConfigData } from "../../utils/types"; @@ -34,13 +27,25 @@ const deploy: DeployFunction = async (hre) => { const prlToken = getTokenAddressFromConfig("prl", config); const wethToken = getTokenAddressFromConfig("weth", config); - const auraBPT = checkAddressValid(sprl2Data.auraBPT, "Aura BPT"); - const auraBoosterLite = checkAddressValid(sprl2Data.auraBoosterLite, "Aura Booster Lite"); - const auraVault = checkAddressValid(sprl2Data.auraVault, "Aura Vault"); - const balancerBPT = checkAddressValid(sprl2Data.balancerBPT, "Balancer BPT"); - + const permit2 = checkAddressValid(sprl2Data.permit2, "Permit2"); const feeReceiver = getWalletAddressFromConfig(sprl2Data.feeReceiver, config); + const balancerRouter = checkAddressValid(sprl2Data.balancerV3Router, "Balancer V3 Router"); + const balancerBPT = checkAddressValid(sprl2Data.balancerBPT, "Balancer BPT"); + const auraBoosterLite = checkAddressValid(sprl2Data.auraBoosterLite, "Aura Booster Lite"); + const auraRewardsPool = checkAddressValid(sprl2Data.auraRewardsPool, "Aura Rewards Pool"); + const auraBPT = checkAddressValid(sprl2Data.auraBPT, "Aura BPT"); + const rewardsTokens = sprl2Data.rewardsTokens.map((token) => checkAddressValid(token, "Reward Token")); + const BPTConfigParams = { + balancerRouter: balancerRouter, + auraBoosterLite: auraBoosterLite, + auraRewardsPool: auraRewardsPool, + balancerBPT: balancerBPT, + prl: prlToken, + weth: wethToken, + rewardTokens: rewardsTokens, + permit2: permit2, + }; const contract = await deploy(contractName, { from: deployer, args: [ @@ -49,15 +54,10 @@ const deploy: DeployFunction = async (hre) => { accessManager, sprl2Data.startPenaltyPercentage, sprl2Data.timeLockDuration, - balancerBPT, - auraBoosterLite, - auraVault, - prlToken, - wethToken, + BPTConfigParams, ], log: true, skipIfAlreadyDeployed: false, - ...GAS, }); console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${contract.address}`); diff --git a/deploy/utils/index.ts b/deploy/utils/index.ts index d6a0ef3..3e01454 100644 --- a/deploy/utils/index.ts +++ b/deploy/utils/index.ts @@ -1,13 +1,7 @@ -import type { CallOptions } from "hardhat-deploy/types"; import { ethers } from "ethers"; import { Address, ConfigData } from "./types"; import { EndpointId } from "@layerzerolabs/lz-definitions"; -export const GAS: CallOptions = { - maxFeePerGas: "20000000000", // 20 gwei - maxPriorityFeePerGas: "1000000000", -}; - export const getLzEidReceiver = (mainchain: string) => { if (mainchain === "sepolia") return EndpointId.SEPOLIA_V2_TESTNET; if (mainchain === "arbiSepolia") return EndpointId.ARBSEP_V2_TESTNET; diff --git a/deploy/utils/types.ts b/deploy/utils/types.ts index 8972662..bcfc308 100644 --- a/deploy/utils/types.ts +++ b/deploy/utils/types.ts @@ -10,7 +10,6 @@ export type ConfigData = { }; tokens: { prl: Address; - paUSD: Address; par: Address; weth: Address; }; @@ -31,13 +30,15 @@ export type ConfigData = { timeLockDuration: number; }; sprl2: { + permit2: Address; feeReceiver: string; startPenaltyPercentage: BigNumberish; timeLockDuration: number; - balancerV3Vault: Address; - auraVault: Address; + balancerV3Router: Address; + auraRewardsPool: Address; auraBoosterLite: Address; auraBPT: Address; balancerBPT: Address; + rewardsTokens: Address[]; }; }; diff --git a/foundry.toml b/foundry.toml index 3319e43..c7a621d 100644 --- a/foundry.toml +++ b/foundry.toml @@ -35,3 +35,4 @@ [rpc_endpoints] mainnet = "https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" +polygon = "https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index f4719b8..bc4d64f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -59,6 +59,16 @@ const config: HardhatUserConfig = { url: getRpcURL("polygon"), verify: getVerifyConfig("polygon"), }, + base: { + url: getRpcURL("base"), + verify: getVerifyConfig("base"), + accounts, + }, + sonic: { + url: getRpcURL("sonic"), + verify: getVerifyConfig("sonic"), + accounts, + }, }, namedAccounts: { deployer: { diff --git a/package.json b/package.json index d153e59..8a0776a 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ }, "dependencies": { "@layerzerolabs/lz-evm-oapp-v2": "^3.0.14", - "@openzeppelin/contracts": "^5.1.0" + "@openzeppelin/contracts": "^5.1.0", + "ts-node": "^10.9.2" }, "devDependencies": { "@commitlint/cli": "^19.5.0", diff --git a/scripts/Base.s.sol b/scripts/Base.s.sol new file mode 100644 index 0000000..d507b0c --- /dev/null +++ b/scripts/Base.s.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { Script, console2 } from "@forge-std/Script.sol"; + +import { IAccessManager } from "@openzeppelin/contracts/access/manager/IAccessManager.sol"; + +contract BaseScript is Script { + /// @dev The address of the transaction broadcaster. + address internal broadcaster; + + IAccessManager accessManager = IAccessManager(0x94Ea8800444017695345156319e96bdB1E355F7a); + + modifier broadcast() { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(privateKey); + broadcaster = vm.addr(privateKey); + _; + vm.stopBroadcast(); + } +} + +library Roles { + uint64 constant GOVERNOR_ROLE = 10; + uint64 constant GOVERNOR_ROLE_TIMELOCK = 11; + uint64 constant GUARDIAN_ROLE = 20; + uint64 constant GUARDIAN_ROLE_TIMELOCK = 21; + uint64 constant KEEPER_ROLE = 30; + uint64 constant KEEPER_ROLE_TIMELOCK = 31; + uint64 constant EURp_MINTER_ROLE = 100; + uint64 constant EURp_MINTER_ROLE_TIMELOCK = 105; + uint64 constant USDp_MINTER_ROLE = 110; + uint64 constant USDp_MINTER_ROLE_TIMELOCK = 115; + uint64 constant ETHp_MINTER_ROLE = 120; + uint64 constant ETHp_MINTER_ROLE_TIMELOCK = 125; + uint64 constant BTCp_MINTER_ROLE = 130; + uint64 constant BTCp_MINTER_ROLE_TIMELOCK = 135; +} diff --git a/scripts/SetMainFeeDistributorRole.s.sol b/scripts/SetMainFeeDistributorRole.s.sol new file mode 100644 index 0000000..4fbcd98 --- /dev/null +++ b/scripts/SetMainFeeDistributorRole.s.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "./Base.s.sol"; + +import { MainFeeDistributor } from "contracts/fees/MainFeeDistributor.sol"; +import { FeeCollectorCore } from "contracts/fees/FeeCollectorCore.sol"; + +contract SetMainFeeDistributorRole is BaseScript { + address mainFeeDistributor = 0x90337e484B1Cb02132fc150d3Afa262147348545; + + function run() public broadcast { + bytes4[] memory guardianSelectors = new bytes4[](3); + guardianSelectors[0] = FeeCollectorCore.pause.selector; + guardianSelectors[1] = FeeCollectorCore.unpause.selector; + guardianSelectors[2] = FeeCollectorCore.emergencyRescue.selector; + accessManager.setTargetFunctionRole(mainFeeDistributor, guardianSelectors, Roles.GUARDIAN_ROLE); + + bytes4[] memory governorSelectors = new bytes4[](2); + governorSelectors[0] = MainFeeDistributor.updateBridgeableToken.selector; + governorSelectors[1] = MainFeeDistributor.updateFeeReceivers.selector; + accessManager.setTargetFunctionRole(mainFeeDistributor, governorSelectors, Roles.GOVERNOR_ROLE); + } +} diff --git a/scripts/SetRewardMerkleDistributor.s.sol b/scripts/SetRewardMerkleDistributor.s.sol new file mode 100644 index 0000000..96140df --- /dev/null +++ b/scripts/SetRewardMerkleDistributor.s.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "./Base.s.sol"; + +import { RewardMerkleDistributor } from "contracts/rewardMerkleDistributor/RewardMerkleDistributor.sol"; + +contract SetRewardMerkleDistributorRole is BaseScript { + address rewardMerkleDistributor = 0x7b54f3D993d3bcA077946034Ea710F9c07420C72; + + function run() public broadcast { + bytes4[] memory guardianSelectors = new bytes4[](3); + guardianSelectors[0] = RewardMerkleDistributor.pause.selector; + guardianSelectors[1] = RewardMerkleDistributor.unpause.selector; + guardianSelectors[2] = RewardMerkleDistributor.emergencyRescue.selector; + accessManager.setTargetFunctionRole(rewardMerkleDistributor, guardianSelectors, Roles.GUARDIAN_ROLE); + + bytes4[] memory governorSelectors = new bytes4[](1); + governorSelectors[0] = RewardMerkleDistributor.updateExpiredRewardsRecipient.selector; + accessManager.setTargetFunctionRole(rewardMerkleDistributor, governorSelectors, Roles.GOVERNOR_ROLE); + + bytes4[] memory keeperSelectors = new bytes4[](1); + keeperSelectors[0] = RewardMerkleDistributor.updateMerkleDrop.selector; + accessManager.setTargetFunctionRole(rewardMerkleDistributor, keeperSelectors, Roles.KEEPER_ROLE); + } +} diff --git a/scripts/SetSPRL1Role.s.sol b/scripts/SetSPRL1Role.s.sol new file mode 100644 index 0000000..00043a1 --- /dev/null +++ b/scripts/SetSPRL1Role.s.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "./Base.s.sol"; + +import { TimeLockPenaltyERC20 } from "contracts/sPRL/TimeLockPenaltyERC20.sol"; + +contract SetSPRL1Role is BaseScript { + address sprl1 = 0x7Df74BBB6F82eC1BCB1562a30ef5Bf5c326e2811; + + function run() public broadcast { + bytes4[] memory guardianSelectors = new bytes4[](2); + guardianSelectors[0] = TimeLockPenaltyERC20.pause.selector; + guardianSelectors[1] = TimeLockPenaltyERC20.unpause.selector; + accessManager.setTargetFunctionRole(sprl1, guardianSelectors, Roles.GUARDIAN_ROLE); + + bytes4[] memory governorSelectors = new bytes4[](3); + governorSelectors[0] = TimeLockPenaltyERC20.updateFeeReceiver.selector; + governorSelectors[1] = TimeLockPenaltyERC20.updateStartPenaltyPercentage.selector; + governorSelectors[2] = TimeLockPenaltyERC20.updateTimeLockDuration.selector; + accessManager.setTargetFunctionRole(sprl1, governorSelectors, Roles.GOVERNOR_ROLE); + } +} diff --git a/scripts/SetSPRL2Role.s.sol b/scripts/SetSPRL2Role.s.sol new file mode 100644 index 0000000..0a3d99a --- /dev/null +++ b/scripts/SetSPRL2Role.s.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "./Base.s.sol"; + +import { sPRL2 } from "contracts/sPRL/sPRL2.sol"; +import { TimeLockPenaltyERC20 } from "contracts/sPRL/TimeLockPenaltyERC20.sol"; + +contract SetSPRL2Role is BaseScript { + address sprl2 = 0x90337e484B1Cb02132fc150d3Afa262147348545; + + function run() public broadcast { + bytes4[] memory guardianSelectors = new bytes4[](2); + guardianSelectors[0] = TimeLockPenaltyERC20.pause.selector; + guardianSelectors[1] = TimeLockPenaltyERC20.unpause.selector; + console2.log("guardianSelectors", guardianSelectors); + // accessManager.setTargetFunctionRole(sprl2, guardianSelectors, Roles.GUARDIAN_ROLE); + + bytes4[] memory governorSelectors = new bytes4[](4); + governorSelectors[0] = TimeLockPenaltyERC20.updateFeeReceiver.selector; + governorSelectors[1] = TimeLockPenaltyERC20.updateStartPenaltyPercentage.selector; + governorSelectors[2] = TimeLockPenaltyERC20.updateTimeLockDuration.selector; + governorSelectors[3] = sPRL2.updateRewardTokens.selector; + console2.log("governorSelectors", governorSelectors); + // accessManager.setTargetFunctionRole(sprl2, governorSelectors, Roles.GOVERNOR_ROLE); + } +} diff --git a/scripts/SetSideChainFeeCollectorRole.s.sol b/scripts/SetSideChainFeeCollectorRole.s.sol new file mode 100644 index 0000000..0595cc8 --- /dev/null +++ b/scripts/SetSideChainFeeCollectorRole.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "./Base.s.sol"; + +import { SideChainFeeCollector } from "contracts/fees/SideChainFeeCollector.sol"; +import { FeeCollectorCore } from "contracts/fees/FeeCollectorCore.sol"; + +contract SetSideChainFeeCollectorRole is BaseScript { + address sideChainFeeCollector = 0x2A4ABC8dcBE2f68E48dFc0db5784C71dB8d5B89c; + + function run() public broadcast { + bytes4[] memory guardianSelectors = new bytes4[](3); + guardianSelectors[0] = FeeCollectorCore.pause.selector; + guardianSelectors[1] = FeeCollectorCore.unpause.selector; + guardianSelectors[2] = FeeCollectorCore.emergencyRescue.selector; + accessManager.setTargetFunctionRole(sideChainFeeCollector, guardianSelectors, Roles.GUARDIAN_ROLE); + + bytes4[] memory governorSelectors = new bytes4[](2); + governorSelectors[0] = SideChainFeeCollector.updateDestinationReceiver.selector; + governorSelectors[1] = SideChainFeeCollector.updateBridgeableToken.selector; + accessManager.setTargetFunctionRole(sideChainFeeCollector, governorSelectors, Roles.GOVERNOR_ROLE); + + bytes4[] memory keeperSelectors = new bytes4[](1); + keeperSelectors[0] = SideChainFeeCollector.swapLzToken.selector; + accessManager.setTargetFunctionRole(sideChainFeeCollector, keeperSelectors, Roles.KEEPER_ROLE); + } +} diff --git a/test/Base.t.sol b/test/Base.t.sol index 2f132e8..901a176 100644 --- a/test/Base.t.sol +++ b/test/Base.t.sol @@ -22,8 +22,6 @@ abstract contract Base_Test is Test, Deploys, Assertions, Defaults, Utils { // Deploy PAR token contract. par = _deployERC20Mock("PAR", "PAR", 18); - // Deploy paUSD token contract. - paUSD = _deployERC20Mock("paUSD", "paUSD", 18); // Deploy PRL token contract. prl = _deployERC20Mock("prl", "PRL", 18); // Deploy BPT token contract. @@ -62,7 +60,6 @@ abstract contract Base_Test is Test, Deploys, Assertions, Defaults, Utils { vm.deal({ account: user.addr, newBalance: INITIAL_BALANCE }); if (setTokenBalance) { par.mint(user.addr, INITIAL_BALANCE); - paUSD.mint(user.addr, INITIAL_BALANCE); prl.mint(user.addr, INITIAL_BALANCE); weth.mint(user.addr, INITIAL_BALANCE); } @@ -81,11 +78,7 @@ abstract contract Base_Test is Test, Deploys, Assertions, Defaults, Utils { address owner = vm.addr(privateKey); deadline = block.timestamp + 1 days; SigUtils.Permit memory permit = SigUtils.Permit({ - owner: owner, - spender: spender, - value: amount, - nonce: IERC20Permit(token).nonces(owner), - deadline: deadline + owner: owner, spender: spender, value: amount, nonce: IERC20Permit(token).nonces(owner), deadline: deadline }); bytes32 digest = sigUtils.getTypedDataHash(permit); diff --git a/test/helpers/Deploys.sol b/test/helpers/Deploys.sol index 8e99edb..ff708da 100644 --- a/test/helpers/Deploys.sol +++ b/test/helpers/Deploys.sol @@ -40,7 +40,6 @@ abstract contract Deploys is Test { ERC20Mock internal par; ERC20Mock internal prl; - ERC20Mock internal paUSD; ERC20Mock internal bpt; ERC20Mock internal auraBpt; diff --git a/test/integrations/rewardMerkleDistributor/claim.t.sol b/test/integrations/rewardMerkleDistributor/claim.t.sol index c54a03f..d3557b4 100644 --- a/test/integrations/rewardMerkleDistributor/claim.t.sol +++ b/test/integrations/rewardMerkleDistributor/claim.t.sol @@ -51,6 +51,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { startTime: uint64(block.timestamp) + firstEpochStartDelay, expiryTime: uint64(block.timestamp) + firstEpochStartDelay + epochLength * 6 }); + rewardMerkleDistributor.updateMerkleDrop(firstEpochId, firstEpochMerkleDrop); /// @dev Leaves are added in the order of the merkle tree's secondEpochLeaves. @@ -94,10 +95,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: firstEpochId, - account: users.alice.addr, - amount: firstClaimRewardsAmount, - merkleProof: proof + epochId: firstEpochId, account: users.alice.addr, amount: firstClaimRewardsAmount, merkleProof: proof }); rewardMerkleDistributor.claims(claimsData); @@ -147,10 +145,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: firstEpochId, - account: users.alice.addr, - amount: firstClaimRewardsAmount, - merkleProof: proof + epochId: firstEpochId, account: users.alice.addr, amount: firstClaimRewardsAmount, merkleProof: proof }); vm.warp(firstEpochMerkleDrop.expiryTime + 1); vm.expectRevert(RewardMerkleDistributor.EpochExpired.selector); @@ -163,10 +158,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: secondEpochId, - account: users.alice.addr, - amount: secondClaimRewardsAmount, - merkleProof: proof + epochId: secondEpochId, account: users.alice.addr, amount: secondClaimRewardsAmount, merkleProof: proof }); vm.expectRevert(RewardMerkleDistributor.NotStarted.selector); rewardMerkleDistributor.claims(claimsData); @@ -179,10 +171,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: firstEpochId, - account: users.alice.addr, - amount: firstClaimRewardsAmount, - merkleProof: proof + epochId: firstEpochId, account: users.alice.addr, amount: firstClaimRewardsAmount, merkleProof: proof }); rewardMerkleDistributor.claims(claimsData); @@ -198,10 +187,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: firstEpochId, - account: users.alice.addr, - amount: firstClaimRewardsAmount * 100, - merkleProof: proof + epochId: firstEpochId, account: users.alice.addr, amount: firstClaimRewardsAmount * 100, merkleProof: proof }); vm.expectRevert(RewardMerkleDistributor.ProofInvalid.selector); @@ -232,10 +218,7 @@ contract RewardMerkleDistributor_Claim_Integrations_Test is Integrations_Test { RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: firstEpochId, - account: users.alice.addr, - amount: firstClaimRewardsAmount, - merkleProof: proof + epochId: firstEpochId, account: users.alice.addr, amount: firstClaimRewardsAmount, merkleProof: proof }); vm.expectRevert(RewardMerkleDistributor.TotalEpochRewardsExceeded.selector); diff --git a/test/integrations/rewardMerkleDistributor/forwardExpiredRewards.t.sol b/test/integrations/rewardMerkleDistributor/forwardExpiredRewards.t.sol index 085212c..06ccb6b 100644 --- a/test/integrations/rewardMerkleDistributor/forwardExpiredRewards.t.sol +++ b/test/integrations/rewardMerkleDistributor/forwardExpiredRewards.t.sol @@ -120,10 +120,7 @@ contract RewardMerkleDistributor_ForwardExpiredRewards_Integrations_Test is Inte RewardMerkleDistributor.ClaimCallData[] memory claimsData = new RewardMerkleDistributor.ClaimCallData[](1); claimsData[0] = RewardMerkleDistributor.ClaimCallData({ - epochId: firstEpochId, - account: users.alice.addr, - amount: firstRewardsAmount, - merkleProof: proof + epochId: firstEpochId, account: users.alice.addr, amount: firstRewardsAmount, merkleProof: proof }); rewardMerkleDistributor.claims(claimsData); @@ -163,9 +160,7 @@ contract RewardMerkleDistributor_ForwardExpiredRewards_Integrations_Test is Inte rewardMerkleDistributor.forwardExpiredRewards(epochIds); } - function test_RewardMerkleDistributor_ForwardExpiredRewards_RevertWhen_EpochIsNotExpired_SeveralEpochs() - external - { + function test_RewardMerkleDistributor_ForwardExpiredRewards_RevertWhen_EpochIsNotExpired_SeveralEpochs() external { vm.startPrank(users.admin.addr); uint64[] memory epochIds = new uint64[](2); epochIds[0] = firstEpochId; diff --git a/test/mocks/BalancerV3RouterMock.sol b/test/mocks/BalancerV3RouterMock.sol index 36eee35..ffa4cc0 100644 --- a/test/mocks/BalancerV3RouterMock.sol +++ b/test/mocks/BalancerV3RouterMock.sol @@ -11,9 +11,11 @@ contract BalancerV3RouterMock is IBalancerV3Router { ERC20Mock public bpt; IPermit2 public permit2; uint256 ratio = 1e18; + bool isReversedBalancerPair; constructor(address[2] memory _tokens, address _bpt, address _permit2) { tokens = _tokens; + isReversedBalancerPair = _tokens[0] > _tokens[1]; bpt = ERC20Mock(_bpt); permit2 = IPermit2(_permit2); } @@ -36,8 +38,12 @@ contract BalancerV3RouterMock is IBalancerV3Router { { uint256 amountIn0 = (maxAmountsIn[0] * ratio) / 1e18; uint256 amountIn1 = (maxAmountsIn[1] * ratio) / 1e18; - permit2.transferFrom(msg.sender, address(this), uint160(amountIn0), tokens[0]); - permit2.transferFrom(msg.sender, address(this), uint160(amountIn1), tokens[1]); + permit2.transferFrom( + msg.sender, address(this), uint160(amountIn0), isReversedBalancerPair ? tokens[1] : tokens[0] + ); + permit2.transferFrom( + msg.sender, address(this), uint160(amountIn1), isReversedBalancerPair ? tokens[0] : tokens[1] + ); bpt.mint(msg.sender, exactBptAmountOut); amountsIn = new uint256[](2); amountsIn[0] = amountIn0; diff --git a/test/mocks/TimeLockPenaltyERC20Mock.sol b/test/mocks/TimeLockPenaltyERC20Mock.sol index e8db9fa..7e47417 100644 --- a/test/mocks/TimeLockPenaltyERC20Mock.sol +++ b/test/mocks/TimeLockPenaltyERC20Mock.sol @@ -14,13 +14,7 @@ contract TimeLockPenaltyERC20Mock is TimeLockPenaltyERC20 { uint64 timeLockDuration ) TimeLockPenaltyERC20( - name, - symbol, - underlying, - feeReceiver, - accessManager, - startPenaltyPercentage, - timeLockDuration + name, symbol, underlying, feeReceiver, accessManager, startPenaltyPercentage, timeLockDuration ) { } } diff --git a/utils/getRpcURL.ts b/utils/getRpcURL.ts index aa2f387..2a77467 100644 --- a/utils/getRpcURL.ts +++ b/utils/getRpcURL.ts @@ -20,6 +20,12 @@ export const getRpcURL = (network: string): string => { case "fantom": { return `https://fantom-mainnet.g.alchemy.com/v2/${apiKey}`; } + case "base": { + return `https://base-mainnet.g.alchemy.com/v2/${apiKey}`; + } + case "sonic": { + return `https://sonic-mainnet.g.alchemy.com/v2/${apiKey}`; + } default: { throw new Error(`${network} Network RPC not configured`); } diff --git a/utils/getVerifyConfig.ts b/utils/getVerifyConfig.ts index 5541052..558c7f4 100644 --- a/utils/getVerifyConfig.ts +++ b/utils/getVerifyConfig.ts @@ -61,6 +61,24 @@ export const getVerifyConfig = (network: string): VerifyConfig => { }, }; } + case "base": { + if (!process.env.BASE_ETHERSCAN_API_KEY) throw new Error("BASE_ETHERSCAN_API_KEY is not set"); + return { + etherscan: { + apiUrl: "https://api.basescan.org", + apiKey: process.env.BASE_ETHERSCAN_API_KEY, + }, + }; + } + case "sonic": { + if (!process.env.SONIC_ETHERSCAN_API_KEY) throw new Error("SONIC_ETHERSCAN_API_KEY is not set"); + return { + etherscan: { + apiUrl: "https://api.sonicscan.org", + apiKey: process.env.SONIC_ETHERSCAN_API_KEY, + }, + }; + } default: { throw new Error(`${network} Network Verify not configured`); }