diff --git a/Makefile b/Makefile index 3ded71e..5320a3e 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ live-deployL1: live-deployL2: @echo "Setting environment variable LIVE_DEPLOY_READ_FILE_NAME to $(file)" - @export LIVE_DEPLOY_READ_FILE_NAME=$(file) && forge script script/deploy/deployAll.s.sol --sig "run(string)" $(file) --fork-url=${L2_RPC_URL} --private-key=$(PRIVATE_KEY) --broadcast --slow + @export LIVE_DEPLOY_READ_FILE_NAME=$(file) && forge script script/deploy/deployAll.s.sol --sig "run(string)" $(file) --fork-url=${L2_RPC_URL} --private-key=$(PRIVATE_KEY) --broadcast --slow --verify prettier: prettier --write '**/*.{md,yml,yaml,ts,js}' diff --git a/deployment-config/chains/1329.json b/deployment-config/chains/1329.json index 4596379..ee6af86 100644 --- a/deployment-config/chains/1329.json +++ b/deployment-config/chains/1329.json @@ -1,5 +1,20 @@ { "name": "Sei", "balancerVault": "0x0000000000000000000000000000000000000000", - "lzEndpoint": "0x1a44076050125825900e736c501f859c50fE728c" + "lzEndpoint": "0x1a44076050125825900e736c501f859c50fE728c", + "assetToRateProviderAndPriceFeed": { + "NOTE_0_CHAINLINK_1_REDSTONE_2_GENERIC": 0, + "NOTE_THESE_KEYS_MUST_NOT_BE_CHECKSUMMED": 0, + "maxTimeFromLastUpdate": "86400", + "0x9faaea2cdd810b21594e54309dc847842ae301ce": { + "denomination": "ETH/seiyanETH", + "priceFeedType": 2, + "target": "0x24152894Decc7384b05E8907D6aDAdD82c176499", + "signature": "getRateSafe()", + "arg": 0, + "expectedMin": "1000000000000000000", + "expectedMax": "1100000000000000000", + "rateProvider": "0x4cb84449fab2812556533491a5c171611a9737fa" + } + } } \ No newline at end of file diff --git a/deployment-config/exampleL1.json b/deployment-config/exampleL1.json index 412064b..fec5e88 100644 --- a/deployment-config/exampleL1.json +++ b/deployment-config/exampleL1.json @@ -53,8 +53,9 @@ }, "rolesAuthority": { "rolesAuthoritySalt": "0x66bbc3b3b3000b01466a3a00000000000000000000000000000000000000001c", - "strategist": "0xC2d99d76bb9D46BF8Ec9449E4DfAE48C30CF0839", - "exchangeRateBot": "0x00000000004F96C07B83e86600D86F0000000000", + "strategist": "0x00000000004F96C07B83e86600D86F0000000000", + "exchangeRateBot": "0x1755397BEc366a1e1160d8aE0106C60E7e344B56", + "pauser": "0xe5CcB29Cb9C886da329098A184302E2D5Ff0cD9E", "address": "0x00000000004F96C07B83e86600D86F0000000000" }, "decoder": { diff --git a/deployment-config/exampleL2.json b/deployment-config/exampleL2.json index 166ff3a..c5eff07 100644 --- a/deployment-config/exampleL2.json +++ b/deployment-config/exampleL2.json @@ -45,8 +45,9 @@ }, "rolesAuthority": { "rolesAuthoritySalt": "0x66bbc3b3b3000b01466a3a00000000000000000000000000000000000000000e", - "strategist": "0xC2d99d76bb9D46BF8Ec9449E4DfAE48C30CF0839", - "exchangeRateBot": "0x00000000004F96C07B83e86600D86F0000000000", + "strategist": "0x00000000004F96C07B83e86600D86F0000000000", + "exchangeRateBot": "0x1755397BEc366a1e1160d8aE0106C60E7e344B56", + "pauser": "0xe5CcB29Cb9C886da329098A184302E2D5Ff0cD9E", "address": "0x00000000004F96C07B83e86600D86F0000000000" }, "decoder": { diff --git a/deployment-config/ssETH-L2.json b/deployment-config/ssETH-L2.json index 10d49d5..ac7c4d9 100644 --- a/deployment-config/ssETH-L2.json +++ b/deployment-config/ssETH-L2.json @@ -28,7 +28,9 @@ "peerEid": 30101, "tellerContractName": "MultiChainLayerZeroTellerWithMultiAssetSupport", "opMessenger": "0x0000000000000000000000000000000000000000", - "assets": [], + "assets": [ + "0x9fAaEA2CDd810b21594E54309DC847842Ae301Ce" + ], "dvnIfNoDefault": { "required": [ "0x6788f52439aca6bff597d3eec2dc9a44b8fee842" diff --git a/script/ConfigReader.s.sol b/script/ConfigReader.s.sol index 9e8a74c..e19a516 100644 --- a/script/ConfigReader.s.sol +++ b/script/ConfigReader.s.sol @@ -45,6 +45,7 @@ library ConfigReader { string tellerContractName; address strategist; address exchangeRateBot; + address pauser; address rolesAuthority; bytes32 decoderSalt; address decoder; @@ -100,6 +101,7 @@ library ConfigReader { config.rolesAuthoritySalt = _config.readBytes32(".rolesAuthority.rolesAuthoritySalt"); config.strategist = _config.readAddress(".rolesAuthority.strategist"); config.exchangeRateBot = _config.readAddress(".rolesAuthority.exchangeRateBot"); + config.pauser = _config.readAddress(".rolesAuthority.pauser"); // Reading from the 'decoder' section config.decoderSalt = _config.readBytes32(".decoder.decoderSalt"); diff --git a/script/deploy/01_DeployRateProviders.s.sol b/script/deploy/01_DeployRateProviders.s.sol index 4d13e97..16f8b01 100644 --- a/script/deploy/01_DeployRateProviders.s.sol +++ b/script/deploy/01_DeployRateProviders.s.sol @@ -132,8 +132,6 @@ contract DeployRateProviders is BaseScript { { bytes4 functionSig = bytes4(keccak256(bytes(signature))); - bytes memory creationCode = type(GenericRateProvider).creationCode; - GenericRateProvider rateProvider = new GenericRateProvider(target, functionSig, bytes32(arg), 0, 0, 0, 0, 0, 0, 0); diff --git a/script/deploy/DeployAtomicQueue.s.sol b/script/deploy/DeployAtomicQueue.s.sol new file mode 100644 index 0000000..29aba4d --- /dev/null +++ b/script/deploy/DeployAtomicQueue.s.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.21; + +import { AtomicQueue } from "./../../src/atomic-queue/AtomicQueue.sol"; +import { BaseScript } from "../Base.s.sol"; +import { stdJson as StdJson } from "@forge-std/StdJson.sol"; + +using StdJson for string; + +bytes32 constant SALT = 0x5bac910c72debe007de61c000000000000000000000000000000000000000000; + +contract DeployAtomicQueue is BaseScript { + function run() public broadcast returns (AtomicQueue atomicQueue) { + bytes memory creationCode = type(AtomicQueue).creationCode; + + atomicQueue = AtomicQueue(CREATEX.deployCreate3(SALT, creationCode)); + } +} diff --git a/script/deploy/single/06_DeployRolesAuthority.s.sol b/script/deploy/single/06_DeployRolesAuthority.s.sol index b2a2352..9c389f4 100644 --- a/script/deploy/single/06_DeployRolesAuthority.s.sol +++ b/script/deploy/single/06_DeployRolesAuthority.s.sol @@ -16,6 +16,7 @@ uint8 constant MANAGER_ROLE = 2; uint8 constant TELLER_ROLE = 3; uint8 constant UPDATE_EXCHANGE_RATE_ROLE = 4; uint8 constant SOLVER_ROLE = 5; +uint8 constant PAUSER_ROLE = 6; /** * NOTE Deploys with `Authority` set to zero bytes. @@ -55,10 +56,6 @@ contract DeployRolesAuthority is BaseScript { ); // Setup initial roles configurations - // --- Users --- - // 1. VAULT_STRATEGIST (BOT EOA) - // 2. MANAGER (CONTRACT) - // 3. TELLER (CONTRACT) // --- Roles --- // 1. STRATEGIST_ROLE // - manager.manageVaultWithMerkleVerification @@ -70,8 +67,22 @@ contract DeployRolesAuthority is BaseScript { // - boringVault.enter() // - boringVault.exit() // - assigned to TELLER - // --- Public --- - // 1. teller.deposit + // 4. PAUSER_ROLE + // - teller.pause() + // - accountant.pause() + // - manager.pause() + // --- Public Functions --- + // 1. teller.deposit() + // 2. teller.bridge() + // 3. teller.depositAndBridge() + // --- Users / Role Assignments --- + // STRATEGIST_ROLE -> OWNER (multisig) + // MANAGER_ROLE -> MANAGER (contract) + // TELLER_ROLE -> TELLER (contract) + // UPDATE_EXCHANGE_RATE_ROLE -> EXCHANGE_RATE_BOT (EOA) & OWNER (multisig) + // PAUSER_ROLE -> PAUSER (EOA) & OWNER (multisig) + + // --- Set Role Capabilities --- rolesAuthority.setRoleCapability( STRATEGIST_ROLE, config.manager, @@ -94,14 +105,23 @@ contract DeployRolesAuthority is BaseScript { rolesAuthority.setRoleCapability(TELLER_ROLE, config.boringVault, BoringVault.exit.selector, true); - rolesAuthority.setPublicCapability(config.teller, TellerWithMultiAssetSupport.deposit.selector, true); - rolesAuthority.setPublicCapability(config.teller, CrossChainTellerBase.bridge.selector, true); - rolesAuthority.setPublicCapability(config.teller, CrossChainTellerBase.depositAndBridge.selector, true); - rolesAuthority.setRoleCapability( UPDATE_EXCHANGE_RATE_ROLE, config.accountant, AccountantWithRateProviders.updateExchangeRate.selector, true ); + rolesAuthority.setRoleCapability(PAUSER_ROLE, config.teller, TellerWithMultiAssetSupport.pause.selector, true); + rolesAuthority.setRoleCapability( + PAUSER_ROLE, config.accountant, AccountantWithRateProviders.pause.selector, true + ); + rolesAuthority.setRoleCapability( + PAUSER_ROLE, config.manager, ManagerWithMerkleVerification.pause.selector, true + ); + + // --- Set Public Capabilities --- + rolesAuthority.setPublicCapability(config.teller, TellerWithMultiAssetSupport.deposit.selector, true); + rolesAuthority.setPublicCapability(config.teller, CrossChainTellerBase.bridge.selector, true); + rolesAuthority.setPublicCapability(config.teller, CrossChainTellerBase.depositAndBridge.selector, true); + // --- Assign roles to users --- rolesAuthority.setUserRole(config.strategist, STRATEGIST_ROLE, true); @@ -110,19 +130,45 @@ contract DeployRolesAuthority is BaseScript { rolesAuthority.setUserRole(config.teller, TELLER_ROLE, true); - rolesAuthority.setUserRole(config.exchangeRateBot, UPDATE_EXCHANGE_RATE_ROLE, true); + rolesAuthority.setUserRole(config.protocolAdmin, UPDATE_EXCHANGE_RATE_ROLE, true); + if (config.exchangeRateBot != address(0)) { + rolesAuthority.setUserRole(config.exchangeRateBot, UPDATE_EXCHANGE_RATE_ROLE, true); + } + + rolesAuthority.setUserRole(config.protocolAdmin, PAUSER_ROLE, true); + if (config.pauser != address(0)) { + rolesAuthority.setUserRole(config.pauser, PAUSER_ROLE, true); + } // Post Deploy Checks require( rolesAuthority.doesUserHaveRole(config.strategist, STRATEGIST_ROLE), "strategist should have STRATEGIST_ROLE" ); + require(rolesAuthority.doesUserHaveRole(config.manager, MANAGER_ROLE), "manager should have MANAGER_ROLE"); + require(rolesAuthority.doesUserHaveRole(config.teller, TELLER_ROLE), "teller should have TELLER_ROLE"); + require( - rolesAuthority.doesUserHaveRole(config.exchangeRateBot, UPDATE_EXCHANGE_RATE_ROLE), - "exchangeRateBot should have UPDATE_EXCHANGE_RATE_ROLE" + rolesAuthority.doesUserHaveRole(config.protocolAdmin, UPDATE_EXCHANGE_RATE_ROLE), + "protocolAdmin should have UPDATE_EXCHANGE_RATE_ROLE" ); + require( + rolesAuthority.doesUserHaveRole(config.protocolAdmin, PAUSER_ROLE), "protocolAdmin should have PAUSER_ROLE" + ); + + if (config.exchangeRateBot != address(0)) { + require( + rolesAuthority.doesUserHaveRole(config.exchangeRateBot, UPDATE_EXCHANGE_RATE_ROLE), + "exchangeRateBot should have UPDATE_EXCHANGE_RATE_ROLE" + ); + } + + if (config.pauser != address(0)) { + require(rolesAuthority.doesUserHaveRole(config.pauser, PAUSER_ROLE), "pauser should have PAUSER_ROLE"); + } + require( rolesAuthority.canCall( config.strategist, @@ -159,11 +205,45 @@ contract DeployRolesAuthority is BaseScript { ), "exchangeRateBot should be able to call accountant.updateExchangeRate" ); + require( + rolesAuthority.canCall( + config.protocolAdmin, config.accountant, AccountantWithRateProviders.updateExchangeRate.selector + ), + "protocolAdmin should be able to call accountant.updateExchangeRate" + ); require( rolesAuthority.canCall(address(1), config.teller, TellerWithMultiAssetSupport.deposit.selector), "anyone should be able to call teller.deposit" ); + // Pauser Roles + _validatePauserRole(config, rolesAuthority, config.protocolAdmin); + if (config.pauser != address(0)) { + _validatePauserRole(config, rolesAuthority, config.pauser); + } + return address(rolesAuthority); } + + function _validatePauserRole( + ConfigReader.Config memory config, + RolesAuthority rolesAuthority, + address user + ) + internal + view + { + require( + rolesAuthority.canCall(user, config.teller, TellerWithMultiAssetSupport.pause.selector), + "pauser should be able to call teller.pause" + ); + require( + rolesAuthority.canCall(user, config.accountant, AccountantWithRateProviders.pause.selector), + "pauser should be able to call accountant.pause" + ); + require( + rolesAuthority.canCall(user, config.manager, ManagerWithMerkleVerification.pause.selector), + "pauser should be able to call manager.pause" + ); + } }