From 5e99001dc55304aa8996139920ba28e1814334a3 Mon Sep 17 00:00:00 2001 From: painiteleo Date: Sun, 9 Jun 2024 00:19:26 +0800 Subject: [PATCH] feat: deploy staking on arbi mainnet --- contracts/abis/LToken.json | 26 + contracts/dependencies.json | 3 +- contracts/deployments.json | 1983 ++++++++++++++++- .../arbi-mainnet-deploy/06-LDYStaking.cts | 49 + .../hardhat/arbi-mainnet-deploy/07-LUSDC.cts | 3 + .../deployments/arbitrum/LDYStaking.json | 1090 +++++++-- .../arbitrum/LDYStaking_Implementation.json | 1741 +++++++++++++++ .../arbitrum/LDYStaking_Proxy.json | 144 ++ .../hardhat/deployments/arbitrum/LUSDC.json | 46 +- .../arbitrum/LUSDC_Implementation.json | 255 ++- .../763174e07eec40e5a74770adce214c49.json | 165 ++ .../8620a8f3d72d00ca5f27836b0fbcc97d.json | 183 ++ .../b5b3f1cfe4b89ed5996f5a0ba11d1ffb.json | 165 ++ .../d4bb825b27822879e0607341255f6d62.json | 165 ++ contracts/src/LToken.sol | 21 +- hardhat.config.cts | 3 +- package.json | 4 +- src/config/chains/index.ts | 2 + src/generated.ts | 353 +-- src/lib/dapp/chains.ts | 2 +- subgraph/build/contracts/abis/LToken.json | 26 + subgraph/build/subgraph.yaml | 14 +- subgraph/config/arbitrum-mainnet.json | 7 + subgraph/generated/LTokenSignaler/LToken.ts | 53 + subgraph/generated/templates/LToken/LToken.ts | 53 + subgraph/subgraph.yaml | 14 +- 26 files changed, 6083 insertions(+), 487 deletions(-) create mode 100644 contracts/hardhat/arbi-mainnet-deploy/06-LDYStaking.cts create mode 100644 contracts/hardhat/arbi-mainnet-deploy/07-LUSDC.cts create mode 100644 contracts/hardhat/deployments/arbitrum/LDYStaking_Implementation.json create mode 100644 contracts/hardhat/deployments/arbitrum/LDYStaking_Proxy.json create mode 100644 contracts/hardhat/deployments/arbitrum/solcInputs/763174e07eec40e5a74770adce214c49.json create mode 100644 contracts/hardhat/deployments/arbitrum/solcInputs/8620a8f3d72d00ca5f27836b0fbcc97d.json create mode 100644 contracts/hardhat/deployments/arbitrum/solcInputs/b5b3f1cfe4b89ed5996f5a0ba11d1ffb.json create mode 100644 contracts/hardhat/deployments/arbitrum/solcInputs/d4bb825b27822879e0607341255f6d62.json create mode 100644 subgraph/config/arbitrum-mainnet.json diff --git a/contracts/abis/LToken.json b/contracts/abis/LToken.json index c3277242..a21f1597 100644 --- a/contracts/abis/LToken.json +++ b/contracts/abis/LToken.json @@ -962,6 +962,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrwalFeeInEth_", + "type": "uint256" + } + ], + "name": "setWithdrwalFeeInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1297,5 +1310,18 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "withdrwalFeeInEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/contracts/dependencies.json b/contracts/dependencies.json index 9a271bef..040b0d7b 100644 --- a/contracts/dependencies.json +++ b/contracts/dependencies.json @@ -1,6 +1,7 @@ { "LDY": { - "1": "0x482dF7483a52496F4C65AB499966dfcdf4DDFDbc" + "1": "0x482dF7483a52496F4C65AB499966dfcdf4DDFDbc", + "42161": "0x999FAF0AF2fF109938eeFE6A7BF91CA56f0D07e1" }, "USDC": { "59144": "0x176211869cA2b568f2A7D4EE941E073a821EE1ff", diff --git a/contracts/deployments.json b/contracts/deployments.json index 57c9220e..db6837ed 100644 --- a/contracts/deployments.json +++ b/contracts/deployments.json @@ -25666,8 +25666,93 @@ ] }, "LDYStaking": { - "address": "0x4e80beDBD58b084a8946b7BA6814c28906Be2d02", + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerSec", + "type": "uint256" + } + ], + "name": "NotifiedRewardAmount", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -25684,49 +25769,1681 @@ "type": "address" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Unstaked", + "type": "event" + }, + { + "inputs": [], + "name": "MULTIPLIER_BASIS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "earned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finishAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getEarnedUser", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "getReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getStakeDurationInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getUserStakes", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakingInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalBlacklist", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalPause", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "highTierAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "globalOwner_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalPause_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalBlacklist_", + "type": "address" + }, + { + "internalType": "address", + "name": "stakeRewardToken_", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo[]", + "name": "stakeDurationInfos_", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdateTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "durationInfo", + "type": "tuple" + } + ], + "name": "pushStakeDurationInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerTokenStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardRatePerSec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setRewardsDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "setStakeAmountForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + } + ], + "name": "setStakeDurationForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "stakeDurationIndex", + "type": "uint8" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakeAmountForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeDurationForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "stakeDurationInfos", + "outputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeRewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "tierOf", + "outputs": [ + { + "internalType": "uint256", + "name": "tier", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStaked", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeightedStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "userStakingInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "LDYStaking_Implementation": { + "address": "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerSec", + "type": "uint256" + } + ], + "name": "NotifiedRewardAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Unstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "MULTIPLIER_BASIS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "earned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finishAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getEarnedUser", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "getReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getStakeDurationInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getUserStakes", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakingInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalBlacklist", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalPause", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "highTierAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "globalOwner_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalPause_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalBlacklist_", + "type": "address" + }, + { + "internalType": "address", + "name": "stakeRewardToken_", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo[]", + "name": "stakeDurationInfos_", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdateTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "durationInfo", + "type": "tuple" + } + ], + "name": "pushStakeDurationInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerTokenStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardRatePerSec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setRewardsDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "setStakeAmountForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + } + ], + "name": "setStakeDurationForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "stakeDurationIndex", + "type": "uint8" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakeAmountForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeDurationForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "stakeDurationInfos", + "outputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeRewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "account", "type": "address" - }, + } + ], + "name": "tierOf", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "tier", + "type": "uint256" } ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "totalRewards", + "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], - "name": "highTierAccounts", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStaked", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", @@ -25734,33 +27451,44 @@ }, { "inputs": [], - "name": "owner", + "name": "totalWeightedStake", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "newOwner", "type": "address" } ], + "name": "transferOwnership", + "outputs": [], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "unstake", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -25769,51 +27497,150 @@ "inputs": [ { "internalType": "address", - "name": "account", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", "type": "address" }, { - "internalType": "bool", - "name": "status", - "type": "bool" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "setHighTierAccount", + "name": "upgradeToAndCall", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "account", + "name": "", "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "tierOf", + "name": "userStakingInfo", "outputs": [ { "internalType": "uint256", - "name": "tier", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", "type": "uint256" } ], "stateMutability": "view", "type": "function" + } + ] + }, + "LDYStaking_Proxy": { + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" } ] }, @@ -26449,6 +28276,12 @@ "internalType": "enum LToken.Status", "name": "newStatus", "type": "uint8" + }, + { + "indexed": false, + "internalType": "int256", + "name": "newId", + "type": "int256" } ], "name": "ActivityEvent", @@ -27310,6 +29143,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrwalFeeInEth_", + "type": "uint256" + } + ], + "name": "setWithdrwalFeeInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -27646,6 +29492,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "withdrwalFeeInEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -27665,7 +29524,7 @@ ] }, "LUSDC_Implementation": { - "address": "0xa2B6487Cc828Ba9260013Ec671F29a4a7778a64B", + "address": "0x8584BCd220A048104e654F842C56E33d37d6aEe3", "abi": [ { "anonymous": false, @@ -28630,6 +30489,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrwalFeeInEth_", + "type": "uint256" + } + ], + "name": "setWithdrwalFeeInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -28965,6 +30837,19 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "withdrwalFeeInEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ] }, diff --git a/contracts/hardhat/arbi-mainnet-deploy/06-LDYStaking.cts b/contracts/hardhat/arbi-mainnet-deploy/06-LDYStaking.cts new file mode 100644 index 00000000..c728e18d --- /dev/null +++ b/contracts/hardhat/arbi-mainnet-deploy/06-LDYStaking.cts @@ -0,0 +1,49 @@ +import { type DeployFunction } from "hardhat-deploy/dist/types"; +import { parseUnits } from "viem"; + +module.exports = (async ({ getNamedAccounts, deployments, getChainId }) => { + const { deployer } = await getNamedAccounts(); + const chainId = await getChainId(); + + const ldyTokenAddress = "0x999FAF0AF2fF109938eeFE6A7BF91CA56f0D07e1"; + + // Retrieve global contracts + const globalOwner = await deployments.get("GlobalOwner"); + const globalPause = await deployments.get("GlobalPause"); + const globalBlacklist = await deployments.get("GlobalBlacklist"); + + const ONE_MONTH = 31 * 24 * 60 * 60; + const stakingDurations = [ + [0 * ONE_MONTH, 10000], // 0 month + [1 * ONE_MONTH, 40000], // 1 month + [6 * ONE_MONTH, 60000], // 6 month + [12 * ONE_MONTH, 100000], // 12 month + // [24 * ONE_MONTH, 30000], // 24 month + // [36 * ONE_MONTH, 40000], // 36 month + ]; + const stakeDurationForPerks = 12 * ONE_MONTH; + const stakeAmountForPerks = parseUnits("1000", 18); + + await deployments.deploy("LDYStaking", { + from: deployer, + log: true, + proxy: { + proxyContract: "UUPS", + execute: { + init: { + methodName: "initialize", + args: [ + globalOwner.address, + globalPause.address, + globalBlacklist.address, + ldyTokenAddress, + stakingDurations, + stakeDurationForPerks, + stakeAmountForPerks, + ], + }, + }, + }, + waitConfirmations: chainId == "31337" ? 1 : 2, + }); +}) as DeployFunction; diff --git a/contracts/hardhat/arbi-mainnet-deploy/07-LUSDC.cts b/contracts/hardhat/arbi-mainnet-deploy/07-LUSDC.cts new file mode 100644 index 00000000..3b7d3e8e --- /dev/null +++ b/contracts/hardhat/arbi-mainnet-deploy/07-LUSDC.cts @@ -0,0 +1,3 @@ +import { deployLToken } from "../lib/deployLToken.cts"; + +module.exports = deployLToken("LUSDC", "USDC"); diff --git a/contracts/hardhat/deployments/arbitrum/LDYStaking.json b/contracts/hardhat/deployments/arbitrum/LDYStaking.json index f29901ea..46f1b00f 100644 --- a/contracts/hardhat/deployments/arbitrum/LDYStaking.json +++ b/contracts/hardhat/deployments/arbitrum/LDYStaking.json @@ -1,6 +1,91 @@ { - "address": "0x4e80beDBD58b084a8946b7BA6814c28906Be2d02", + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerSec", + "type": "uint256" + } + ], + "name": "NotifiedRewardAmount", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -11,55 +96,715 @@ "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Unstaked", + "type": "event" + }, + { + "inputs": [], + "name": "MULTIPLIER_BASIS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "earned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finishAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getEarnedUser", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "getReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getStakeDurationInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getUserStakes", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakingInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalBlacklist", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalPause", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "highTierAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "globalOwner_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalPause_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalBlacklist_", + "type": "address" + }, + { + "internalType": "address", + "name": "stakeRewardToken_", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo[]", + "name": "stakeDurationInfos_", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdateTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "durationInfo", + "type": "tuple" + } + ], + "name": "pushStakeDurationInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerTokenStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardRatePerSec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setRewardsDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "setStakeAmountForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + } + ], + "name": "setStakeDurationForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "stakeDurationIndex", + "type": "uint8" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakeAmountForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeDurationForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "stakeDurationInfos", + "outputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" } ], - "name": "OwnershipTransferred", - "type": "event" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "name": "stakeRewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "", + "name": "account", "type": "address" } ], - "name": "highTierAccounts", + "name": "tierOf", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", + "name": "tier", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRewards", + "outputs": [ + { + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", @@ -67,12 +812,12 @@ }, { "inputs": [], - "name": "owner", + "name": "totalStaked", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -80,20 +825,44 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "totalWeightedStake", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", "type": "address" } ], + "name": "transferOwnership", + "outputs": [], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "unstake", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -102,33 +871,71 @@ "inputs": [ { "internalType": "address", - "name": "account", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", "type": "address" }, { - "internalType": "bool", - "name": "status", - "type": "bool" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "setHighTierAccount", + "name": "upgradeToAndCall", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "account", + "name": "", "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "tierOf", + "name": "userStakingInfo", "outputs": [ { "internalType": "uint256", - "name": "tier", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", "type": "uint256" } ], @@ -139,152 +946,117 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "_logic", "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" } ], - "transactionHash": "0x210704e38f3e5db512c78ea1b01fb73e2df1480179b8f5c1012bec0a8d781c31", + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", "receipt": { "to": null, - "from": "0x9644fFCE92Ff305f14AF9aCD71c7ccbBE6478023", - "contractAddress": "0x4e80beDBD58b084a8946b7BA6814c28906Be2d02", - "transactionIndex": 1, - "gasUsed": "3224942", - "logsBloom": "0x00000400000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000800000001000000000000000000000000000000000000020000000000010000000800000000000000000000000000000000400000000000000000000000002000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2aad5ac9d3307ed324e40b640ca8f9b7d8a6a842fff0a7efcaebfac9dd58032d", - "transactionHash": "0x210704e38f3e5db512c78ea1b01fb73e2df1480179b8f5c1012bec0a8d781c31", + "from": "0x0F97f63dA69A5b86Fe47517459D982198Cba22D2", + "contractAddress": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "transactionIndex": 9, + "gasUsed": "2191924", + "logsBloom": "0x00000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000200000000000000000000020000000000000000000040100000000000000000000100000000000000020000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcbd958b21081734c47ba6011a31430494cd445e45e914f0a4884c5be24e65f91", + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", "logs": [ { - "transactionIndex": 1, - "blockNumber": 165375406, - "transactionHash": "0x210704e38f3e5db512c78ea1b01fb73e2df1480179b8f5c1012bec0a8d781c31", - "address": "0x4e80beDBD58b084a8946b7BA6814c28906Be2d02", + "transactionIndex": 9, + "blockNumber": 218746026, + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009644ffce92ff305f14af9acd71c7ccbbe6478023" + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000067efae630f0f7fae539b0f1eb1fc1c4cc4dc3e47" ], "data": "0x", - "logIndex": 0, - "blockHash": "0x2aad5ac9d3307ed324e40b640ca8f9b7d8a6a842fff0a7efcaebfac9dd58032d" + "logIndex": 14, + "blockHash": "0xcbd958b21081734c47ba6011a31430494cd445e45e914f0a4884c5be24e65f91" + }, + { + "transactionIndex": 9, + "blockNumber": 218746026, + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 15, + "blockHash": "0xcbd958b21081734c47ba6011a31430494cd445e45e914f0a4884c5be24e65f91" } ], - "blockNumber": 165375406, - "cumulativeGasUsed": "3224942", + "blockNumber": 218746026, + "cumulativeGasUsed": "5043212", "status": 1, "byzantium": true }, - "args": [], - "numDeployments": 2, - "solcInputHash": "d74114448a35b14f4563775ab35bca2b", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"highTierAccounts\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"status\",\"type\":\"bool\"}],\"name\":\"setHighTierAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"tierOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tier\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Lila Rest (https://lila.rest)\",\"custom:security-contact\":\"security@ledgity.comsecurity@ledgity.com\",\"details\":\"This contract only implements tierOf() function from LDYStaking as it's the only one the LToken contract relies on.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setHighTierAccount(address,bool)\":{\"params\":{\"account\":\"The account to update the high tier status of.\"}},\"tierOf(address)\":{\"details\":\"Dummy tierOf() function that always return that the given account is not ellgible to any LDY staking tier, except if the account is in the defaultToHighestTier mapping.\",\"params\":{\"account\":\"The account to check the tier of.\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"highTierAccounts\":{\"details\":\"This is notably used to allow PreMining contracts to benefit from 0% withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\"}},\"title\":\"LDYStaking\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"highTierAccounts(address)\":{\"notice\":\"Holds a mapping of addresses that default to the highest staking tier.\"},\"setHighTierAccount(address,bool)\":{\"notice\":\"Update high tier status of a given account.\"}},\"notice\":\"Replacement to the LDYStaking contract until the $LDY token is available and the real LDYStaking can be deployed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/src/DummyLDYStaking.sol\":\"LDYStaking\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable2Step.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Ownable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2Step is Ownable {\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n}\\n\",\"keccak256\":\"0xde231558366826d7cb61725af8147965a61c53b77a352cc8c9af38fc5a92ac3c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/src/DummyLDYStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Ownable2Step} from \\\"@openzeppelin/contracts/access/Ownable2Step.sol\\\";\\n\\n/**\\n * @title LDYStaking\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Replacement to the LDYStaking contract until the $LDY token is available and\\n * the real LDYStaking can be deployed.\\n *\\n * @dev This contract only implements tierOf() function from LDYStaking as it's the only\\n * one the LToken contract relies on.\\n *\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract LDYStaking is Ownable2Step {\\n /**\\n * @notice Holds a mapping of addresses that default to the highest staking tier.\\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\\n */\\n mapping(address => bool) public highTierAccounts;\\n\\n /**\\n * @notice Update high tier status of a given account.\\n * @param account The account to update the high tier status of.\\n */\\n function setHighTierAccount(address account, bool status) public onlyOwner {\\n highTierAccounts[account] = status;\\n }\\n\\n /**\\n * @dev Dummy tierOf() function that always return that the given account is not\\n * ellgible to any LDY staking tier, except if the account is in the\\n * defaultToHighestTier mapping.\\n * @param account The account to check the tier of.\\n */\\n function tierOf(address account) public view returns (uint256 tier) {\\n if (highTierAccounts[account]) return 3;\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x8f21c11de734a54181725bc34349590b950117be72b6b67fb81f044364a77544\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061001a3361001f565b610096565b600180546001600160a01b031916905561004381610046602090811b6102bc17901c565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61042f806100a56000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063c66120f41161005b578063c66120f4146100dc578063c8f74bb81461010f578063e30c397814610130578063f2fde38b1461014157600080fd5b80634c1fa4b91461008d578063715018a6146100a257806379ba5097146100aa5780638da5cb5b146100b2575b600080fd5b6100a061009b36600461039b565b610154565b005b6100a0610187565b6100a061019b565b6000546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6100ff6100ea3660046103d7565b60026020526000908152604090205460ff1681565b60405190151581526020016100d3565b61012261011d3660046103d7565b61021a565b6040519081526020016100d3565b6001546001600160a01b03166100bf565b6100a061014f3660046103d7565b61024b565b61015c61030c565b6001600160a01b03919091166000908152600260205260409020805460ff1916911515919091179055565b61018f61030c565b6101996000610366565b565b60015433906001600160a01b0316811461020e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61021781610366565b50565b6001600160a01b03811660009081526002602052604081205460ff161561024357506003919050565b506000919050565b61025361030c565b600180546001600160a01b0383166001600160a01b031990911681179091556102846000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146101995760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610205565b600180546001600160a01b0319169055610217816102bc565b80356001600160a01b038116811461039657600080fd5b919050565b600080604083850312156103ae57600080fd5b6103b78361037f565b9150602083013580151581146103cc57600080fd5b809150509250929050565b6000602082840312156103e957600080fd5b6103f28261037f565b939250505056fea264697066735822122066bb653abd8f5c2da5419714c3d62e191812126ae71c8483413b5c36930aa8af64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063c66120f41161005b578063c66120f4146100dc578063c8f74bb81461010f578063e30c397814610130578063f2fde38b1461014157600080fd5b80634c1fa4b91461008d578063715018a6146100a257806379ba5097146100aa5780638da5cb5b146100b2575b600080fd5b6100a061009b36600461039b565b610154565b005b6100a0610187565b6100a061019b565b6000546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6100ff6100ea3660046103d7565b60026020526000908152604090205460ff1681565b60405190151581526020016100d3565b61012261011d3660046103d7565b61021a565b6040519081526020016100d3565b6001546001600160a01b03166100bf565b6100a061014f3660046103d7565b61024b565b61015c61030c565b6001600160a01b03919091166000908152600260205260409020805460ff1916911515919091179055565b61018f61030c565b6101996000610366565b565b60015433906001600160a01b0316811461020e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61021781610366565b50565b6001600160a01b03811660009081526002602052604081205460ff161561024357506003919050565b506000919050565b61025361030c565b600180546001600160a01b0383166001600160a01b031990911681179091556102846000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146101995760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610205565b600180546001600160a01b0319169055610217816102bc565b80356001600160a01b038116811461039657600080fd5b919050565b600080604083850312156103ae57600080fd5b6103b78361037f565b9150602083013580151581146103cc57600080fd5b809150509250929050565b6000602082840312156103e957600080fd5b6103f28261037f565b939250505056fea264697066735822122066bb653abd8f5c2da5419714c3d62e191812126ae71c8483413b5c36930aa8af64736f6c63430008120033", + "args": [ + "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", + "0x63d07120000000000000000000000000e4af4573bfc5f04d8b84c61744de8a94059f2462000000000000000000000000d4d4c68ce70fa88b9e527dd3a4a6d19c5cbdd4db000000000000000000000000ca55a2394876e7cf52e99ab36fc9151a7d9cf350000000000000000000000000999faf0af2ff109938eefe6a7bf91ca56f0d07e100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000001ea6e0000000000000000000000000000000000000000000000003635c9adc5dea00000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000028de800000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000f53700000000000000000000000000000000000000000000000000000000000000ea600000000000000000000000000000000000000000000000000000000001ea6e0000000000000000000000000000000000000000000000000000000000000186a0" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":\"ERC1967Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161084e38038061084e83398101604081905261002291610349565b61004d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610417565b600080516020610807833981519152146100695761006961043c565b6100758282600061007c565b50506104a1565b610085836100b2565b6000825111806100925750805b156100ad576100ab83836100f260201b6100291760201c565b505b505050565b6100bb8161011e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606101178383604051806060016040528060278152602001610827602791396101de565b9392505050565b610131816102bc60201b6100551760201c565b6101985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101bd60008051602061080783398151915260001b6102cb60201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161018f565b600080856001600160a01b0316856040516102619190610452565b600060405180830381855af49150503d806000811461029c576040519150601f19603f3d011682016040523d82523d6000602084013e6102a1565b606091505b5090925090506102b28282866102ce565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102dd575081610117565b8251156102ed5782518084602001fd5b8160405162461bcd60e51b815260040161018f919061046e565b634e487b7160e01b600052604160045260246000fd5b60005b83811015610338578181015183820152602001610320565b838111156100ab5750506000910152565b6000806040838503121561035c57600080fd5b82516001600160a01b038116811461037357600080fd5b60208401519092506001600160401b038082111561039057600080fd5b818501915085601f8301126103a457600080fd5b8151818111156103b6576103b6610307565b604051601f8201601f19908116603f011681019083821181831017156103de576103de610307565b816040528281528860208487010111156103f757600080fd5b61040883602083016020880161031d565b80955050505050509250929050565b60008282101561043757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825161046481846020870161031d565b9190910192915050565b602081526000825180602084015261048d81604085016020870161031d565b601f01601f19169190910160400192915050565b610357806104b06000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033", + "execute": { + "methodName": "initialize", + "args": [ + "0xe4Af4573bFc5F04D8b84c61744de8A94059f2462", + "0xd4D4c68CE70fa88B9E527DD3A4a6d19c5cbdd4dB", + "0xcA55A2394876e7Cf52e99Ab36Fc9151a7d9CF350", + "0x999FAF0AF2fF109938eeFE6A7BF91CA56f0D07e1", + [ + [ + 0, + 10000 + ], + [ + 2678400, + 40000 + ], + [ + 16070400, + 60000 + ], + [ + 32140800, + 100000 + ] + ], + 32140800, + "1000000000000000000000" + ] + }, + "implementation": "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", "devdoc": { - "author": "Lila Rest (https://lila.rest)", - "custom:security-contact": "security@ledgity.comsecurity@ledgity.com", - "details": "This contract only implements tierOf() function from LDYStaking as it's the only one the LToken contract relies on.", + "details": "This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.", "kind": "dev", "methods": { - "acceptOwnership()": { - "details": "The new owner accepts the ownership transfer." - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "pendingOwner()": { - "details": "Returns the address of the pending owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." - }, - "setHighTierAccount(address,bool)": { - "params": { - "account": "The account to update the high tier status of." - } - }, - "tierOf(address)": { - "details": "Dummy tierOf() function that always return that the given account is not ellgible to any LDY staking tier, except if the account is in the defaultToHighestTier mapping.", - "params": { - "account": "The account to check the tier of." - } - }, - "transferOwnership(address)": { - "details": "Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner." - } - }, - "stateVariables": { - "highTierAccounts": { - "details": "This is notably used to allow PreMining contracts to benefit from 0% withdrawal fees in L-Tokens contracts, when accounts unlock their funds." + "constructor": { + "details": "Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor." } }, - "title": "LDYStaking", "version": 1 }, "userdoc": { "kind": "user", - "methods": { - "highTierAccounts(address)": { - "notice": "Holds a mapping of addresses that default to the highest staking tier." - }, - "setHighTierAccount(address,bool)": { - "notice": "Update high tier status of a given account." - } - }, - "notice": "Replacement to the LDYStaking contract until the $LDY token is available and the real LDYStaking can be deployed.", + "methods": {}, "version": 1 }, "storageLayout": { - "storage": [ - { - "astId": 2904, - "contract": "contracts/src/DummyLDYStaking.sol:LDYStaking", - "label": "_owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 3017, - "contract": "contracts/src/DummyLDYStaking.sol:LDYStaking", - "label": "_pendingOwner", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 4710, - "contract": "contracts/src/DummyLDYStaking.sol:LDYStaking", - "label": "highTierAccounts", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_bool)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => bool)", - "numberOfBytes": "32", - "value": "t_bool" - } - } + "storage": [], + "types": null } } \ No newline at end of file diff --git a/contracts/hardhat/deployments/arbitrum/LDYStaking_Implementation.json b/contracts/hardhat/deployments/arbitrum/LDYStaking_Implementation.json new file mode 100644 index 00000000..e322ea9d --- /dev/null +++ b/contracts/hardhat/deployments/arbitrum/LDYStaking_Implementation.json @@ -0,0 +1,1741 @@ +{ + "address": "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerSec", + "type": "uint256" + } + ], + "name": "NotifiedRewardAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Unstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "MULTIPLIER_BASIS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "earned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finishAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getEarnedUser", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "getReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getStakeDurationInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getUserStakes", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakingInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalBlacklist", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalPause", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "highTierAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "globalOwner_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalPause_", + "type": "address" + }, + { + "internalType": "address", + "name": "globalBlacklist_", + "type": "address" + }, + { + "internalType": "address", + "name": "stakeRewardToken_", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo[]", + "name": "stakeDurationInfos_", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdateTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "internalType": "struct LDYStaking.StakeDurationInfo", + "name": "durationInfo", + "type": "tuple" + } + ], + "name": "pushStakeDurationInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardPerTokenStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardRatePerSec", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setRewardsDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeAmountForPerks_", + "type": "uint256" + } + ], + "name": "setStakeAmountForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stakeDurationForPerks_", + "type": "uint256" + } + ], + "name": "setStakeDurationForPerks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "stakeDurationIndex", + "type": "uint8" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakeAmountForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeDurationForPerks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "stakeDurationInfos", + "outputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeRewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "tierOf", + "outputs": [ + { + "internalType": "uint256", + "name": "tier", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStaked", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalWeightedStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stakeIndex", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "userStakingInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unStakeAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardPerTokenPaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xd28ebf04e243c2cfa86dc6344e5261ea22e172cd0b5b5bfb4302c23d16ae2da4", + "receipt": { + "to": null, + "from": "0x0F97f63dA69A5b86Fe47517459D982198Cba22D2", + "contractAddress": "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", + "transactionIndex": 2, + "gasUsed": "9398240", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x28dc1882bbbc1100ff403aed422af9da9b6b44ddd15d08c389cb942803c431d8", + "transactionHash": "0xd28ebf04e243c2cfa86dc6344e5261ea22e172cd0b5b5bfb4302c23d16ae2da4", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 218746007, + "transactionHash": "0xd28ebf04e243c2cfa86dc6344e5261ea22e172cd0b5b5bfb4302c23d16ae2da4", + "address": "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 0, + "blockHash": "0x28dc1882bbbc1100ff403aed422af9da9b6b44ddd15d08c389cb942803c431d8" + } + ], + "blockNumber": 218746007, + "cumulativeGasUsed": "9530771", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "8620a8f3d72d00ca5f27836b0fbcc97d", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardPerSec\",\"type\":\"uint256\"}],\"name\":\"NotifiedRewardAmount\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"stakeIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"name\":\"RewardPaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"stakeIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Staked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"stakeIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Unstaked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MULTIPLIER_BASIS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"stakeIndex\",\"type\":\"uint256\"}],\"name\":\"earned\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finishAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getEarnedUser\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"stakeIndex\",\"type\":\"uint256\"}],\"name\":\"getReward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getStakeDurationInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplier\",\"type\":\"uint256\"}],\"internalType\":\"struct LDYStaking.StakeDurationInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getUserStakes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stakedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unStakeAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rewardPerTokenPaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rewards\",\"type\":\"uint256\"}],\"internalType\":\"struct LDYStaking.StakingInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalBlacklist\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalPause\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"highTierAccounts\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"globalOwner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"globalPause_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"globalBlacklist_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"stakeRewardToken_\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplier\",\"type\":\"uint256\"}],\"internalType\":\"struct LDYStaking.StakeDurationInfo[]\",\"name\":\"stakeDurationInfos_\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"stakeDurationForPerks_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"stakeAmountForPerks_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTimeRewardApplicable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastUpdateTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplier\",\"type\":\"uint256\"}],\"internalType\":\"struct LDYStaking.StakeDurationInfo\",\"name\":\"durationInfo\",\"type\":\"tuple\"}],\"name\":\"pushStakeDurationInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"recoverERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rewardPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rewardPerTokenStored\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rewardRatePerSec\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rewardsDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"setRewardsDuration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"stakeAmountForPerks_\",\"type\":\"uint256\"}],\"name\":\"setStakeAmountForPerks\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"stakeDurationForPerks_\",\"type\":\"uint256\"}],\"name\":\"setStakeDurationForPerks\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"stakeDurationIndex\",\"type\":\"uint8\"}],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakeAmountForPerks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakeDurationForPerks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stakeDurationInfos\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplier\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakeRewardToken\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"tierOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tier\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalStaked\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWeightedStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"stakeIndex\",\"type\":\"uint256\"}],\"name\":\"unstake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"userStakingInfo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"stakedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unStakeAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rewardPerTokenPaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rewards\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:security-contact\":\"security@ledgity.comsecurity@ledgity.com\",\"details\":\"This contract implements tierOf() function from LDYStaking as it's the only one the LToken contract relies on.\",\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is changed.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"NotifiedRewardAmount(uint256,uint256)\":{\"params\":{\"rewardAmount\":\"Reward amount added by admin.\",\"rewardPerSec\":\"RewardRatePerSec updated.\"}},\"Paused(address)\":{\"details\":\"Emitted when the pause is triggered by `account`.\"},\"RewardPaid(address,uint256,uint256)\":{\"params\":{\"reward\":\"Reward token amount\",\"stakeIndex\":\"User staking pool index\",\"user\":\"User address\"}},\"Staked(address,uint256,uint256)\":{\"params\":{\"amount\":\"Staked amount\",\"stakeIndex\":\"Latest index of user staking pool\",\"user\":\"User address\"}},\"Unpaused(address)\":{\"details\":\"Emitted when the pause is lifted by `account`.\"},\"Unstaked(address,uint256,uint256)\":{\"params\":{\"amount\":\"Staked amount\",\"stakeIndex\":\"User staking pool index\",\"user\":\"User address\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"earned(address,uint256)\":{\"params\":{\"account\":\"Address of the user.\",\"stakeIndex\":\"Index of the stakePool\"},\"returns\":{\"_0\":\"Return earned amounts\"}},\"getEarnedUser(address)\":{\"params\":{\"account\":\"Address of the user.\"},\"returns\":{\"_0\":\"Return earned rewards array for a user.\"}},\"getReward(uint256)\":{\"details\":\"Emits a `RewardPaid` event upon successful reward claim.\",\"params\":{\"stakeIndex\":\"The index of user staking pool.\"}},\"getStakeDurationInfo(uint256)\":{\"params\":{\"index\":\"Index of StakeDurationInfos.\"},\"returns\":{\"_0\":\"StakeDurationInfo.\"}},\"getUserStakes(address)\":{\"params\":{\"account\":\"The address of user.\"},\"returns\":{\"_0\":\"StakingInfo array.\"}},\"globalBlacklist()\":{\"returns\":{\"_0\":\"The address of the GlobalBlacklist contract.\"}},\"globalOwner()\":{\"returns\":{\"_0\":\"The address of the GlobalOwner contract.\"}},\"globalPause()\":{\"returns\":{\"_0\":\"The address of the GlobalPause contract.\"}},\"initialize(address,address,address,address,(uint256,uint256)[],uint256,uint256)\":{\"details\":\"This function is intended for setting initial values for the contract's state variables.\",\"params\":{\"globalBlacklist_\":\"The address of the GlobalBlacklist contract.\",\"globalOwner_\":\"The address of the GlobalOwner contract.\",\"globalPause_\":\"The address of the GlobalPause contract.\",\"stakeAmountForPerks_\":\"Minimal staking amount for perks.\",\"stakeDurationForPerks_\":\"Minimal staking duration for perks.\",\"stakeDurationInfos_\":\"Available Staking Durations.\",\"stakeRewardToken_\":\"The address of stake and reward token(LDY token).\"}},\"lastTimeRewardApplicable()\":{\"returns\":{\"_0\":\"Timestamp of the most recent rewards calculation.\"}},\"notifyRewardAmount(uint256)\":{\"details\":\"Only callable by owner.\",\"params\":{\"amount\":\"The amount of reward to be distributed.\"}},\"owner()\":{\"returns\":{\"_0\":\"The address of the owner\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether the contract is paused or not.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"pushStakeDurationInfo((uint256,uint256))\":{\"details\":\"Only callable by owner.\"},\"recoverERC20(address,uint256)\":{\"params\":{\"amount\":\"The amount of token to recover.\",\"tokenAddress\":\"The address of the token to recover.\"}},\"rewardPerToken()\":{\"returns\":{\"_0\":\"Current reward per token.\"}},\"setRewardsDuration(uint256)\":{\"details\":\"Only callable by owner, and setting available only after rewards period.\",\"params\":{\"duration\":\"New reward duration in seconds.\"}},\"setStakeAmountForPerks(uint256)\":{\"details\":\"Only callable by owner.\",\"params\":{\"stakeAmountForPerks_\":\"New stakeDurationForPerks.\"}},\"setStakeDurationForPerks(uint256)\":{\"details\":\"Only callable by owner.\",\"params\":{\"stakeDurationForPerks_\":\"New stakeDurationForPerks.\"}},\"stake(uint256,uint8)\":{\"details\":\"Emits a `Staked` event upon successful staking.\",\"params\":{\"amount\":\"The amount of tokens to stake.\",\"stakeDurationIndex\":\"The Index of stakeDurationInfos array.\"}},\"tierOf(address)\":{\"details\":\"tierOf() function that always return that the given account is not elligible to any LDY staking tier, except if the account is in the highTierAccounts mapping.\",\"params\":{\"account\":\"The account to check the tier of.\"}},\"unstake(uint256,uint256)\":{\"details\":\"Emits a `Unstaked` event upon successful withdrawal. On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\",\"params\":{\"amount\":\"The amount of tokens to withdraw.\",\"stakeIndex\":\"The index of user staking pool\"}},\"upgradeTo(address)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"stateVariables\":{\"highTierAccounts\":{\"details\":\"This is notably used to allow PreMining contracts to benefit from 0% withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\"}},\"title\":\"LDYStaking\",\"version\":1},\"userdoc\":{\"events\":{\"NotifiedRewardAmount(uint256,uint256)\":{\"notice\":\"Emitted when admin add rewards.\"},\"RewardPaid(address,uint256,uint256)\":{\"notice\":\"Emitted when users claim rewards\"},\"Staked(address,uint256,uint256)\":{\"notice\":\"Emitted when users stake token\"},\"Unstaked(address,uint256,uint256)\":{\"notice\":\"Emitted when users unstake token\"}},\"kind\":\"user\",\"methods\":{\"MULTIPLIER_BASIS()\":{\"notice\":\"Decimals of multiplier\"},\"earned(address,uint256)\":{\"notice\":\"Calculate the user's stake pool earnings\"},\"finishAt()\":{\"notice\":\"Timestamp of when the rewards finish.\"},\"getEarnedUser(address)\":{\"notice\":\"Get the earned rewards array for a user.\"},\"getReward(uint256)\":{\"notice\":\"Claim pending rewards.\"},\"getStakeDurationInfo(uint256)\":{\"notice\":\"Get StakeDurationInfo.\"},\"getUserStakes(address)\":{\"notice\":\"Get User Stake Data.\"},\"globalBlacklist()\":{\"notice\":\"Retrieves the address of GlobalBlacklist contract.\"},\"globalOwner()\":{\"notice\":\"Retrieves the address of GlobalOwner contract.\"},\"globalPause()\":{\"notice\":\"Retrieves the address of GlobalPause contract.\"},\"highTierAccounts(address)\":{\"notice\":\"Holds a mapping of addresses that default to the highest staking tier.\"},\"initialize(address,address,address,address,(uint256,uint256)[],uint256,uint256)\":{\"notice\":\"Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\"},\"lastTimeRewardApplicable()\":{\"notice\":\"Get the last time when rewards were applicable for the specified reward token.\"},\"lastUpdateTime()\":{\"notice\":\"Timestamp of the reward updated.\"},\"notifyRewardAmount(uint256)\":{\"notice\":\"Notify the contract about the amount of rewards to be distributed and update reward parameters.\"},\"owner()\":{\"notice\":\"Override of OwnableUpgradeable.owner() that retrieves the owner's address from the GlobalOwner contract instead.\"},\"paused()\":{\"notice\":\"Override of PausableUpgradeable.pause() that retrieves the pause state from the GlobalPause contract instead.\"},\"pushStakeDurationInfo((uint256,uint256))\":{\"notice\":\"Push stakeDurationInfo\"},\"recoverERC20(address,uint256)\":{\"notice\":\"Recovers a specified amount of a given token address. Will fail if the contract doesn't hold enough tokens.\"},\"renounceOwnership()\":{\"notice\":\"Override of OwnableUpgradeable.renounceOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there.\"},\"rewardPerToken()\":{\"notice\":\"Calculate the reward per token for a given reward token.\"},\"rewardPerTokenStored()\":{\"notice\":\"Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\"},\"rewardRatePerSec()\":{\"notice\":\"Reward per second(total rewards / duration).\"},\"rewardsDuration()\":{\"notice\":\"Duration of the rewards (in seconds).\"},\"setRewardsDuration(uint256)\":{\"notice\":\"Update Rewards Duration.\"},\"setStakeAmountForPerks(uint256)\":{\"notice\":\"Update stakeAmountForPerks\"},\"setStakeDurationForPerks(uint256)\":{\"notice\":\"Update stakeDurationForPerks\"},\"stake(uint256,uint8)\":{\"notice\":\"Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\"},\"stakeAmountForPerks()\":{\"notice\":\"Minimal stake amount for perks.\"},\"stakeDurationForPerks()\":{\"notice\":\"Minimal stake duration for perks.\"},\"stakeDurationInfos(uint256)\":{\"notice\":\"Stake durations info array.\"},\"stakeRewardToken()\":{\"notice\":\"Stake and Reward token.\"},\"totalRewards()\":{\"notice\":\"Total rewards amount.\"},\"totalStaked()\":{\"notice\":\"Total staked amounts.\"},\"transferOwnership(address)\":{\"notice\":\"Override of OwnableUpgradeable.transferOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there.\"},\"unstake(uint256,uint256)\":{\"notice\":\"Withdraw staked tokens after stakeDuration has passed.\"},\"userStakingInfo(address,uint256)\":{\"notice\":\"User stakingInfo map, user address => array of the staking info\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/src/LDYStaking.sol\":\"LDYStaking\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n *\\n * _Available since v4.8.3._\\n */\\ninterface IERC1967Upgradeable {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0x47d6e06872b12e72c79d1b5eb55842f860b5fb1207b2317c2358d2766b950a7b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822ProxiableUpgradeable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeaconUpgradeable.sol\\\";\\nimport \\\"../../interfaces/IERC1967Upgradeable.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822Upgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/StorageSlotUpgradeable.sol\\\";\\nimport \\\"../utils/Initializable.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\\n function __ERC1967Upgrade_init() internal onlyInitializing {\\n }\\n\\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\\n }\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(AddressUpgradeable.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(AddressUpgradeable.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\\n }\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x584ebdf9c1118a7c773f98788e3f3ede01982bdf8932aa06f5acc7d54876e161\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeaconUpgradeable {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../interfaces/draft-IERC1822Upgradeable.sol\\\";\\nimport \\\"../ERC1967/ERC1967UpgradeUpgradeable.sol\\\";\\nimport \\\"./Initializable.sol\\\";\\n\\n/**\\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\\n *\\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\\n * `UUPSUpgradeable` with a custom implementation of upgrades.\\n *\\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n require(address(this) != __self, \\\"Function must be called through delegatecall\\\");\\n require(_getImplementation() == __self, \\\"Function must be called through active proxy\\\");\\n _;\\n }\\n\\n /**\\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\\n * callable on the implementing contract but not through proxies.\\n */\\n modifier notDelegated() {\\n require(address(this) == __self, \\\"UUPSUpgradeable: must not be called through delegatecall\\\");\\n _;\\n }\\n\\n /**\\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\\n */\\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\\n return _IMPLEMENTATION_SLOT;\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeTo(address newImplementation) public virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\\n * encoded in `data`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {upgradeTo} and {upgradeToAndCall}.\\n *\\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\\n *\\n * ```solidity\\n * function _authorizeUpgrade(address) internal override onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xb607cb94c27e89750f5ae2ccebcb94e654e926f6125f4fd4c6262c89875118ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\\n * _Available since v4.9 for `string`, `bytes`._\\n */\\nlibrary StorageSlotUpgradeable {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07ac95acad040f1fb1f6120dd0aa5f702db69446e95f82613721879d30de0908\",\"license\":\"MIT\"},\"contracts/src/GlobalBlacklist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./abstracts/GlobalOwnableUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalBlacklist\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Holds a global mapping of blacklisted accounts shared by all contracts of the\\n * Ledgity Yield codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\\n * and getter functions to easily check against this global blacklist.\\n *\\n * @dev For further details, see \\\"GlobalBlacklist\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\\n /**\\n * @notice Mapping of accounts to their blacklist status.\\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\\n */\\n mapping(address => bool) private _list;\\n\\n /// @dev Emitted when `account` is blacklisted.\\n event Blacklisted(address account);\\n\\n /// @dev Emitted when `account` is unblacklisted.\\n event Unblacklisted(address account);\\n\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function initialize(address globalOwner_) public initializer {\\n __GlobalOwnable_init(globalOwner_);\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @notice Adds a given account to the blacklist.\\n * @param account The account's address to be blacklisted.\\n */\\n function blacklist(address account) external onlyOwner {\\n require(account != address(0), \\\"L20\\\");\\n _list[account] = true;\\n emit Blacklisted(account);\\n }\\n\\n /**\\n * @notice Removes a given account from the blacklist.\\n * @param account The account's address to be un-blacklisted.\\n */\\n function unBlacklist(address account) external onlyOwner {\\n _list[account] = false;\\n emit Unblacklisted(account);\\n }\\n\\n /**\\n * @notice Checks whether a given account is blacklisted.\\n * @param account Address of the account to check.\\n * @return 'true' if the account is blacklisted, 'false' otherwise\\n */\\n function isBlacklisted(address account) external view returns (bool) {\\n // Gas optimization: Avoid accessing storage if account is the zero address\\n // (e.g, during a mint or a burn of tokens)\\n if (account == address(0)) return false;\\n\\n // Else, return current account's blacklist status\\n return _list[account];\\n }\\n}\\n\",\"keccak256\":\"0x7e771076a06cfec935df22cf2d307df7e1f7df5b887976ec1dea30f8b68a878d\",\"license\":\"MIT\"},\"contracts/src/GlobalOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {Ownable2StepUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalOwner\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Holds the address of a global owner account shared by all contracts of the\\n * Ledgity Yield's codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\\n * owner() function that retrieves the owner's address from this contract instead.\\n *\\n * @dev For further details, see \\\"GlobalOwner\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n */\\n function initialize() public initializer {\\n __Ownable2Step_init();\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0xa3b880c4d82e796c162c99a398b569ce4a8e6d27232014b81a6a4503718f12dc\",\"license\":\"MIT\"},\"contracts/src/GlobalPause.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./abstracts/GlobalOwnableUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalPause\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Holds a global pause state shared by all contracts of the Ledgity Yield\\n * codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\\n * paused() function that retrieves the pause state from this contract instead.\\n *\\n * @dev For further details, see \\\"GlobalPause\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalPause is\\n Initializable,\\n UUPSUpgradeable,\\n GlobalOwnableUpgradeable,\\n PausableUpgradeable\\n{\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function initialize(address globalOwner_) public initializer {\\n __GlobalOwnable_init(globalOwner_);\\n __Pausable_init();\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\\n * but restricted to contract's owner.\\n */\\n function pause() public onlyOwner {\\n _pause();\\n }\\n\\n function unpause() public onlyOwner {\\n _unpause();\\n }\\n}\\n\",\"keccak256\":\"0x9a0767e761dbd1d5800db03558c3903f229e6ef29f5fe5ff38f45fb4d7572e2e\",\"license\":\"MIT\"},\"contracts/src/LDYStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n// Contracts\\nimport {ReentrancyGuardUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport {BaseUpgradeable} from \\\"./abstracts/base/BaseUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @title LDYStaking\\n * @custom:security-contact security@ledgity.com\\n *\\n * @dev This contract implements tierOf() function from LDYStaking as it's the only\\n * one the LToken contract relies on.\\n *\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract LDYStaking is BaseUpgradeable, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /**\\n * @notice Represents a user staking info in array.\\n * @param stakedAmount Amount of the stake.\\n * @param unStakeAt Unstake at.\\n * @param duration Staking period in seconds.\\n * @param rewardPerTokenPaid Reward per token paid.\\n * @param rewards Rewards to be claimed.\\n */\\n struct StakingInfo {\\n uint256 stakedAmount;\\n uint256 unStakeAt;\\n uint256 duration;\\n uint256 rewardPerTokenPaid;\\n uint256 rewards;\\n }\\n\\n /**\\n * @notice Represent duration and multiplier per each stake option.\\n * @param duration Staking period in seconds.\\n * @param multiplier Token weight\\n */\\n struct StakeDurationInfo {\\n uint256 duration;\\n uint256 multiplier;\\n }\\n\\n /// @notice Decimals of multiplier\\n uint256 public constant MULTIPLIER_BASIS = 1e4;\\n\\n /// @notice Stake and Reward token.\\n IERC20Upgradeable public stakeRewardToken;\\n\\n /// @notice Minimal stake duration for perks.\\n uint256 public stakeDurationForPerks;\\n\\n /// @notice Minimal stake amount for perks.\\n uint256 public stakeAmountForPerks;\\n\\n /// @notice Stake durations info array.\\n StakeDurationInfo[] public stakeDurationInfos;\\n\\n /// @notice Duration of the rewards (in seconds).\\n uint256 public rewardsDuration;\\n\\n /// @notice Timestamp of when the rewards finish.\\n uint256 public finishAt;\\n\\n /// @notice Timestamp of the reward updated.\\n uint256 public lastUpdateTime;\\n\\n /// @notice Reward per second(total rewards / duration).\\n uint256 public rewardRatePerSec;\\n\\n /// @notice Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\\n uint256 public rewardPerTokenStored;\\n\\n /// @notice Total staked amounts.\\n uint256 public totalStaked;\\n\\n // Total staked amounts with multiplier applied\\n uint256 public totalWeightedStake;\\n\\n /// @notice User stakingInfo map, user address => array of the staking info\\n mapping(address => StakingInfo[]) public userStakingInfo;\\n\\n /// @notice Total rewards amount.\\n uint256 public totalRewards;\\n\\n /**\\n * @notice Emitted when users stake token\\n * @param user User address\\n * @param stakeIndex Latest index of user staking pool\\n * @param amount Staked amount\\n */\\n event Staked(address indexed user, uint256 stakeIndex, uint256 amount);\\n\\n /**\\n * @notice Emitted when users unstake token\\n * @param user User address\\n * @param stakeIndex User staking pool index\\n * @param amount Staked amount\\n */\\n event Unstaked(address indexed user, uint256 stakeIndex, uint256 amount);\\n\\n /**\\n * @notice Emitted when users claim rewards\\n * @param user User address\\n * @param stakeIndex User staking pool index\\n * @param reward Reward token amount\\n */\\n event RewardPaid(address indexed user, uint256 stakeIndex, uint256 reward);\\n\\n /**\\n * @notice Emitted when admin add rewards.\\n * @param rewardAmount Reward amount added by admin.\\n * @param rewardPerSec RewardRatePerSec updated.\\n */\\n event NotifiedRewardAmount(uint256 rewardAmount, uint256 rewardPerSec);\\n\\n /**\\n * @notice Holds a mapping of addresses that default to the highest staking tier.\\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\\n */\\n mapping(address => bool) public highTierAccounts;\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\\n * @dev This function is intended for setting initial values for the contract's state variables.\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param stakeRewardToken_ The address of stake and reward token(LDY token).\\n * @param stakeDurationInfos_ Available Staking Durations.\\n * @param stakeDurationForPerks_ Minimal staking duration for perks.\\n * @param stakeAmountForPerks_ Minimal staking amount for perks.\\n */\\n function initialize(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n address stakeRewardToken_,\\n StakeDurationInfo[] memory stakeDurationInfos_,\\n uint256 stakeDurationForPerks_,\\n uint256 stakeAmountForPerks_\\n ) public initializer {\\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\\n stakeRewardToken = IERC20Upgradeable(stakeRewardToken_);\\n uint stakeDurationInfosLength = stakeDurationInfos_.length;\\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\\n stakeDurationInfos.push(stakeDurationInfos_[i]);\\n }\\n stakeDurationForPerks = stakeDurationForPerks_;\\n stakeAmountForPerks = stakeAmountForPerks_;\\n }\\n\\n // --------------------\\n // MUTATIVE FUNCTIONS\\n // --------------------\\n\\n /**\\n * @notice Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\\n * @dev Emits a `Staked` event upon successful staking.\\n * @param amount The amount of tokens to stake.\\n * @param stakeDurationIndex The Index of stakeDurationInfos array.\\n */\\n function stake(\\n uint256 amount,\\n uint8 stakeDurationIndex\\n ) external nonReentrant whenNotPaused notBlacklisted(_msgSender()) {\\n require(amount > 0, \\\"amount = 0\\\");\\n require(stakeDurationIndex <= stakeDurationInfos.length - 1, \\\"Invalid staking period\\\");\\n\\n _updateReward(address(0), 0);\\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[stakeDurationIndex];\\n StakingInfo memory stakingInfo = StakingInfo({\\n stakedAmount: amount,\\n unStakeAt: block.timestamp + stakeDurationInfo.duration,\\n duration: stakeDurationInfo.duration,\\n rewardPerTokenPaid: rewardPerTokenStored,\\n rewards: 0\\n });\\n\\n // check whether account is eligible for benefit from the protocol\\n if (stakeDurationInfo.duration >= stakeDurationForPerks && amount >= stakeAmountForPerks) {\\n highTierAccounts[_msgSender()] = true;\\n }\\n\\n userStakingInfo[_msgSender()].push(stakingInfo);\\n\\n uint256 stakeIndex = userStakingInfo[_msgSender()].length - 1;\\n uint256 weightedStake = (amount * stakeDurationInfo.multiplier) / MULTIPLIER_BASIS;\\n totalWeightedStake += weightedStake;\\n totalStaked += amount;\\n\\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\\n\\n emit Staked(_msgSender(), stakeIndex, amount);\\n }\\n\\n /**\\n * @notice Withdraw staked tokens after stakeDuration has passed.\\n * @dev Emits a `Unstaked` event upon successful withdrawal.\\n * On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\\n * @param amount The amount of tokens to withdraw.\\n * @param stakeIndex The index of user staking pool\\n */\\n function unstake(\\n uint256 amount,\\n uint256 stakeIndex\\n ) external nonReentrant notBlacklisted(_msgSender()) {\\n require(amount > 0, \\\"amount = 0\\\");\\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \\\"Invalid stakeIndex\\\");\\n require(\\n block.timestamp >= userStakingInfo[_msgSender()][stakeIndex].unStakeAt,\\n \\\"Cannot unstake during staking period\\\"\\n );\\n require(\\n amount <= userStakingInfo[_msgSender()][stakeIndex].stakedAmount,\\n \\\"Insufficient unstake amount\\\"\\n );\\n\\n _updateReward(_msgSender(), stakeIndex);\\n\\n uint256 multiplier = _getMultiplier(userStakingInfo[_msgSender()][stakeIndex].duration);\\n\\n uint256 currentWeightedStake = (amount * multiplier) / MULTIPLIER_BASIS;\\n totalWeightedStake -= currentWeightedStake;\\n\\n totalStaked -= amount;\\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount -= amount;\\n\\n // check whether account is eligible for benefit from the protocol\\n if (\\n userStakingInfo[_msgSender()][stakeIndex].duration >= stakeDurationForPerks &&\\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount < stakeAmountForPerks\\n ) {\\n highTierAccounts[_msgSender()] = false;\\n }\\n\\n // remove staking info from array on full withdrawal\\n if (userStakingInfo[_msgSender()][stakeIndex].stakedAmount == 0) {\\n _claimReward(_msgSender(), stakeIndex);\\n\\n userStakingInfo[_msgSender()][stakeIndex] = userStakingInfo[_msgSender()][\\n userStakingInfo[_msgSender()].length - 1\\n ];\\n userStakingInfo[_msgSender()].pop();\\n }\\n stakeRewardToken.safeTransfer(_msgSender(), amount);\\n\\n emit Unstaked(_msgSender(), stakeIndex, amount);\\n }\\n\\n /**\\n * @notice Claim pending rewards.\\n * @dev Emits a `RewardPaid` event upon successful reward claim.\\n * @param stakeIndex The index of user staking pool.\\n */\\n function getReward(uint256 stakeIndex) external nonReentrant notBlacklisted(_msgSender()) {\\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \\\"Invalid stakeIndex\\\");\\n _updateReward(_msgSender(), stakeIndex);\\n _claimReward(_msgSender(), stakeIndex);\\n }\\n\\n // --------------------\\n // ADMIN CONFIGURATION\\n // --------------------\\n\\n /**\\n * @notice Update Rewards Duration.\\n * @dev Only callable by owner, and setting available only after rewards period.\\n * @param duration New reward duration in seconds.\\n */\\n function setRewardsDuration(uint256 duration) external onlyOwner {\\n require(finishAt < block.timestamp, \\\"reward duration is not finished\\\");\\n rewardsDuration = duration;\\n }\\n\\n /**\\n * @notice Update stakeDurationForPerks\\n * @dev Only callable by owner.\\n * @param stakeDurationForPerks_ New stakeDurationForPerks.\\n */\\n function setStakeDurationForPerks(uint256 stakeDurationForPerks_) external onlyOwner {\\n stakeDurationForPerks = stakeDurationForPerks_;\\n }\\n\\n /**\\n * @notice Update stakeAmountForPerks\\n * @dev Only callable by owner.\\n * @param stakeAmountForPerks_ New stakeDurationForPerks.\\n */\\n function setStakeAmountForPerks(uint256 stakeAmountForPerks_) external onlyOwner {\\n stakeAmountForPerks = stakeAmountForPerks_;\\n }\\n\\n /**\\n * @notice Push stakeDurationInfo\\n * @dev Only callable by owner.\\n */\\n function pushStakeDurationInfo(StakeDurationInfo memory durationInfo) external onlyOwner {\\n stakeDurationInfos.push(durationInfo);\\n }\\n\\n /**\\n * @notice Notify the contract about the amount of rewards to be distributed and update reward parameters.\\n * @dev Only callable by owner.\\n * @param amount The amount of reward to be distributed.\\n */\\n function notifyRewardAmount(uint256 amount) external onlyOwner {\\n require(rewardsDuration > 0, \\\"rewards duration is not set\\\");\\n require(amount > 0, \\\"amount = 0\\\");\\n\\n _updateReward(address(0), 0);\\n\\n if (block.timestamp >= finishAt) {\\n rewardRatePerSec = amount / rewardsDuration;\\n } else {\\n uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatePerSec;\\n rewardRatePerSec = (amount + remainingRewards) / rewardsDuration;\\n }\\n\\n require(rewardRatePerSec > 0, \\\"reward rate = 0\\\");\\n require(\\n rewardRatePerSec <=\\n (stakeRewardToken.balanceOf(address(this)) + amount - totalStaked) /\\n rewardsDuration,\\n \\\"reward amount > balance\\\"\\n );\\n\\n finishAt = block.timestamp + rewardsDuration;\\n lastUpdateTime = block.timestamp;\\n\\n totalRewards += amount;\\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\\n\\n emit NotifiedRewardAmount(amount, rewardRatePerSec);\\n }\\n\\n // --------------------\\n // VIEW FUNCTIONS\\n // --------------------\\n\\n /**\\n * @notice Get the last time when rewards were applicable for the specified reward token.\\n * @return Timestamp of the most recent rewards calculation.\\n */\\n function lastTimeRewardApplicable() public view returns (uint256) {\\n return _min(finishAt, block.timestamp);\\n }\\n\\n /**\\n * @notice Calculate the reward per token for a given reward token.\\n * @return Current reward per token.\\n */\\n function rewardPerToken() public view returns (uint256) {\\n if (totalStaked == 0) {\\n return rewardPerTokenStored;\\n }\\n\\n return\\n rewardPerTokenStored +\\n ((rewardRatePerSec * (lastTimeRewardApplicable() - lastUpdateTime) * 1e18) /\\n totalWeightedStake);\\n }\\n\\n /**\\n * @notice Calculate the user's stake pool earnings\\n * @param account Address of the user.\\n * @param stakeIndex Index of the stakePool\\n * @return Return earned amounts\\n */\\n function earned(address account, uint256 stakeIndex) public view returns (uint256) {\\n StakingInfo memory userInfo = userStakingInfo[account][stakeIndex];\\n uint256 multiplier = _getMultiplier(userInfo.duration);\\n uint256 weightedAmount = (userInfo.stakedAmount * multiplier) / MULTIPLIER_BASIS;\\n uint256 rewardsSinceLastUpdate = ((weightedAmount *\\n (rewardPerToken() - userInfo.rewardPerTokenPaid)) / 1e18);\\n return rewardsSinceLastUpdate + userInfo.rewards;\\n }\\n\\n /**\\n * @notice Get the earned rewards array for a user.\\n * @param account Address of the user.\\n * @return Return earned rewards array for a user.\\n */\\n function getEarnedUser(address account) public view returns (uint256[] memory) {\\n uint256 numberOfPools = userStakingInfo[account].length;\\n uint256[] memory earnedArray = new uint256[](numberOfPools);\\n for (uint256 index; index < numberOfPools; index++) {\\n earnedArray[index] = earned(account, index);\\n }\\n return earnedArray;\\n }\\n\\n /**\\n * @dev tierOf() function that always return that the given account is not\\n * elligible to any LDY staking tier, except if the account is in the\\n * highTierAccounts mapping.\\n * @param account The account to check the tier of.\\n */\\n function tierOf(address account) public view returns (uint256 tier) {\\n if (highTierAccounts[account]) return 3;\\n return 0;\\n }\\n\\n /**\\n * @notice Get User Stake Data.\\n * @param account The address of user.\\n * @return StakingInfo array.\\n */\\n function getUserStakes(address account) external view returns (StakingInfo[] memory) {\\n return userStakingInfo[account];\\n }\\n\\n /**\\n * @notice Get StakeDurationInfo.\\n * @param index Index of StakeDurationInfos.\\n * @return StakeDurationInfo.\\n */\\n function getStakeDurationInfo(uint256 index) external view returns (StakeDurationInfo memory) {\\n require(stakeDurationInfos.length - 1 >= index, \\\"wrong index\\\");\\n return stakeDurationInfos[index];\\n }\\n\\n /**\\n * @notice Send rewards to user.\\n * @dev This is private function, called by getReward function.\\n * @param account The address of user.\\n * @param stakeIndex The index of user staking pool.\\n */\\n function _claimReward(address account, uint256 stakeIndex) private {\\n uint256 reward = userStakingInfo[account][stakeIndex].rewards;\\n\\n if (reward > 0) {\\n userStakingInfo[account][stakeIndex].rewards = 0;\\n totalRewards -= reward;\\n stakeRewardToken.safeTransfer(account, reward);\\n emit RewardPaid(account, stakeIndex, reward);\\n }\\n }\\n\\n /**\\n * @notice Calculate and update user rewards per stakeIndex.\\n * @dev this is private function, called by stake, unstake, getRewards, and notifyRewardAmount functions.\\n * @param account The address of user.\\n * @param stakeIndex The index of user staking pool.\\n */\\n function _updateReward(address account, uint256 stakeIndex) private {\\n rewardPerTokenStored = rewardPerToken();\\n lastUpdateTime = lastTimeRewardApplicable();\\n\\n if (account != address(0)) {\\n userStakingInfo[account][stakeIndex].rewards = earned(account, stakeIndex);\\n userStakingInfo[account][stakeIndex].rewardPerTokenPaid = rewardPerTokenStored;\\n }\\n }\\n\\n /**\\n * @notice Get multiplier from stakeDurationInfo based on duration\\n * @param duration Stake Duration\\n */\\n function _getMultiplier(uint256 duration) private view returns (uint256) {\\n uint256 stakeDurationInfosLength = stakeDurationInfos.length;\\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[i];\\n if (duration == stakeDurationInfo.duration) {\\n return stakeDurationInfo.multiplier;\\n }\\n }\\n return 0;\\n }\\n\\n /**\\n * @notice Take minimum value between x and y.\\n */\\n function _min(uint256 x, uint256 y) private pure returns (uint256) {\\n return x <= y ? x : y;\\n }\\n}\\n\",\"keccak256\":\"0x7e6eba9f67c4a0ad1ade18149d04fe01a53bae4cc3a898a8ab0b347c1d036cc5\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalOwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {OwnableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {GlobalOwner} from \\\"../GlobalOwner.sol\\\";\\n\\n/**\\n * @title GlobalOwnableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\\n * contract (see GlobalOwner.sol). This design facilitates centralized management\\n * of ownership for all the Ledgity Yield contracts.\\n *\\n * @dev Security measure:\\n * The _globalOwner state must be set at initialization time and, for evident security\\n * reasons, cannot be changed afterward.\\n *\\n * @dev For further details, see \\\"GlobalOwnableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\\n /**\\n * @notice The GlobalOwner contract the ownership will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalOwner private _globalOwner;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\\n __GlobalOwnable_init_unchained(globalOwner_);\\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\\n // the initial _owner value, calling it would have no effect.\\n }\\n\\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\\n _globalOwner = GlobalOwner(globalOwner_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalOwner contract.\\n * @return The address of the GlobalOwner contract.\\n */\\n function globalOwner() public view returns (address) {\\n return address(_globalOwner);\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\\n * from the GlobalOwner contract instead.\\n * @return The address of the owner\\n */\\n function owner() public view override returns (address) {\\n return _globalOwner.owner();\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\\n * Ownership is managed by the GlobalOwner contract and must be modified there.\\n */\\n function transferOwnership(address newOwner) public view override onlyOwner {\\n newOwner; // Silence unused variable compiler warning\\n revert(\\\"L8\\\");\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\\n * Ownership is managed by the GlobalOwner contract and must be modified there.\\n */\\n function renounceOwnership() public view override onlyOwner {\\n revert(\\\"L65\\\");\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x9203f7a2a19def126d8ff0fde8357053ffcf1100d65ec8faec8299b6ed2c0c5a\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalPausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {GlobalPause} from \\\"../GlobalPause.sol\\\";\\n\\n/**\\n * @title GlobalPausableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit a pause state from the specified GlobalPause\\n * contract (see GlobalPause.sol). This design facilitates centralized management of\\n * pause state for all the Ledgity Yield contracts.\\n *\\n * @dev Security measure\\n * The _globalPause state must be set at initialization time and, for evident security\\n * reasons, cannot be changed afterward.\\n *\\n * @dev For further details, see \\\"GlobalPausableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\\n /**\\n * @notice The GlobalPause contract the pause state will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalPause private _globalPause;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalPause_ The address of the GlobalPause contract.\\n */\\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\\n __Pausable_init();\\n __GlobalPausable_init_unchained(globalPause_);\\n }\\n\\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\\n _globalPause = GlobalPause(globalPause_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalPause contract.\\n * @return The address of the GlobalPause contract.\\n */\\n function globalPause() public view returns (address) {\\n return address(_globalPause);\\n }\\n\\n /**\\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\\n * from the GlobalPause contract instead.\\n * @return Whether the contract is paused or not.\\n */\\n function paused() public view virtual override returns (bool) {\\n return _globalPause.paused();\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xff508c0b8c48916885453b4894d0401e94580fb24fb6af1885a3e160864cde94\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalRestrictableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalBlacklist} from \\\"../GlobalBlacklist.sol\\\";\\n\\n/**\\n * @title GlobalRestrictableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit a blacklist state from the specified\\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\\n * centralized management of a blacklist for all the Ledgity Yield contracts.\\n *\\n * @dev Security measure:\\n * The _globalBlacklist state must be set at initialization time and, for evident\\n * security reasons, cannot be changed afterward.\\n *\\n * @dev For further details, see \\\"GlobalRestrictableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalRestrictableUpgradeable is Initializable {\\n /**\\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalBlacklist private _globalBlacklist;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n */\\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\\n __GlobalRestrictable_init_unchained(globalBlacklist_);\\n }\\n\\n function __GlobalRestrictable_init_unchained(\\n address globalBlacklist_\\n ) internal onlyInitializing {\\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalBlacklist contract.\\n * @return The address of the GlobalBlacklist contract.\\n */\\n function globalBlacklist() public view returns (address) {\\n return address(_globalBlacklist);\\n }\\n\\n /**\\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\\n * @param account Address to verify.\\n */\\n modifier notBlacklisted(address account) {\\n require(isBlacklisted(account) == false, \\\"L9\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\\n * @param account Address to verify.\\n * @return Whether the account is blacklisted.\\n */\\n function isBlacklisted(address account) internal view returns (bool) {\\n return _globalBlacklist.isBlacklisted(account);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x0032fde90d9cf23e70dd4b604ae0d1ed3283f117bc24f68d32f8933e1bd372bc\",\"license\":\"MIT\"},\"contracts/src/abstracts/RecoverableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n// Conracts\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./GlobalOwnableUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @title RecoverableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts are provided with helper functions allowing the recovery of\\n * assets accidentally sent to them.\\n *\\n * @dev Where are utilities Ether, ERC721, etc.?\\n * This abstract contract currently supports only ERC20 tokens. Derived contracts\\n * in this codebase currently do not implement the necessary functions to receive Ether\\n * or ERC721/ERC1155 tokens, so no recovery functions are provided for these assets.\\n *\\n * @dev For further details, see \\\"RecoverableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\\n __GlobalOwnable_init(globalOwner_);\\n __Recoverable_init_unchained();\\n }\\n\\n function __Recoverable_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Recovers a specified amount of a given token address. Will fail if the\\n * contract doesn't hold enough tokens.\\n * @param tokenAddress The address of the token to recover.\\n * @param amount The amount of token to recover.\\n */\\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\\n // Ensure the specified amount is not zero\\n require(amount > 0, \\\"L10\\\");\\n\\n // Create a reference to token's contract\\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\\n\\n // Ensure there is enough token to recover\\n require(tokenContract.balanceOf(address(this)) >= amount, \\\"L11\\\");\\n\\n // Transfer the recovered token amount to the sender\\n tokenContract.safeTransfer(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xc70110d1284c9e4aa7c518b3b98682dd9edbe6f6fb23761d825554ba41a80d5e\",\"license\":\"MIT\"},\"contracts/src/abstracts/base/BaseUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"../GlobalPausableUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"../GlobalOwnableUpgradeable.sol\\\";\\nimport {GlobalRestrictableUpgradeable} from \\\"../GlobalRestrictableUpgradeable.sol\\\";\\nimport {RecoverableUpgradeable} from \\\"../RecoverableUpgradeable.sol\\\";\\n\\n/**\\n * @title BaseUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This abstract contract acts as a base for numerous contracts in this codebase,\\n * minimizing code repetition and enhancing readability and maintainability.\\n *\\n * @dev For further details, see \\\"Base\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract BaseUpgradeable is\\n Initializable,\\n UUPSUpgradeable,\\n GlobalOwnableUpgradeable,\\n GlobalPausableUpgradeable,\\n GlobalRestrictableUpgradeable,\\n RecoverableUpgradeable\\n{\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n */\\n function __Base_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_\\n ) internal onlyInitializing {\\n __UUPSUpgradeable_init();\\n __GlobalOwnable_init(globalOwner_);\\n __Pausable_init();\\n __GlobalPausable_init_unchained(globalPause_);\\n __GlobalRestrictable_init_unchained(globalBlacklist_);\\n __Recoverable_init_unchained();\\n }\\n\\n function __Base_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xe445c759682f31d39e63663ff8217072c0e81086bda11ea473247be334c3e424\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a0604052306080523480156200001557600080fd5b506200002062000030565b6200002a62000030565b620000f1565b600054610100900460ff16156200009d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000ef576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6080516130c06200012960003960008181610b1501528181610b5501528181610f8601528181610fc6015261103e01526130c06000f3fe6080604052600436106102515760003560e01c8063817b1cd211610139578063c8f33c91116100b6578063df136d651161007a578063df136d65146106e5578063eed9da1f146106fc578063f12d54d814610713578063f2fde38b14610732578063f6c3565014610752578063f762e7341461077357600080fd5b8063c8f33c9114610662578063c8f74bb814610679578063cc1a378f14610699578063cd3daf9d146106b9578063cedaf639146106ce57600080fd5b80639e2c8a5b116100fd5780639e2c8a5b1461059f578063a029e898146105bf578063bddff592146105fa578063be01d6c714610611578063c66120f41461063157600080fd5b8063817b1cd21461050f578063842e2981146105265780638980f11f146105535780638da5cb5b146105735780639b602f0a1461058857600080fd5b80634f1ef286116101d257806367d3b4881161019657806367d3b48814610459578063715018a614610470578063793e875e146104855780637b2cca38146104a55780637c2edb16146104d257806380faa57d146104fa57600080fd5b80634f1ef286146103b757806352d1902d146103ca5780635c046e66146103df5780635c975abb1461041457806363d071201461043957600080fd5b8063386a952511610219578063386a95251461032a5780633c6b16ab146103415780633e491d471461036157806340a8d39f146103815780634a7f48041461039757600080fd5b806304d978f1146102565780630e15561a146102a357806310087fb1146102c85780631c4b774b146102ea5780633659cfe61461030a575b600080fd5b34801561026257600080fd5b50610276610271366004612984565b610791565b604080519586526020860194909452928401919091526060830152608082015260a0015b60405180910390f35b3480156102af57600080fd5b506102ba6102365481565b60405190815260200161029a565b3480156102d457600080fd5b506102e86102e33660046129b0565b6107e0565b005b3480156102f657600080fd5b506102e86103053660046129e6565b610a7e565b34801561031657600080fd5b506102e86103253660046129ff565b610b0b565b34801561033657600080fd5b506102ba61022e5481565b34801561034d57600080fd5b506102e861035c3660046129e6565b610bd0565b34801561036d57600080fd5b506102ba61037c366004612984565b610e6c565b34801561038d57600080fd5b506102ba61271081565b3480156103a357600080fd5b506102e86103b23660046129e6565b610f6e565b6102e86103c5366004612a63565b610f7c565b3480156103d657600080fd5b506102ba611031565b3480156103eb57600080fd5b506103ff6103fa3660046129e6565b6110df565b6040805192835260208301919091520161029a565b34801561042057600080fd5b5061042961110e565b604051901515815260200161029a565b34801561044557600080fd5b506102e8610454366004612b5a565b611182565b34801561046557600080fd5b506102ba61022f5481565b34801561047c57600080fd5b506102e861132a565b34801561049157600080fd5b506102e86104a0366004612c6b565b611360565b3480156104b157600080fd5b506104c56104c03660046129ff565b6113d2565b60405161029a9190612c87565b3480156104de57600080fd5b50610161546001600160a01b03165b60405161029a9190612ccb565b34801561050657600080fd5b506102ba611480565b34801561051b57600080fd5b506102ba6102335481565b34801561053257600080fd5b506105466105413660046129ff565b61148f565b60405161029a9190612cdf565b34801561055f57600080fd5b506102e861056e366004612984565b611537565b34801561057f57600080fd5b506104ed611633565b34801561059457600080fd5b506102ba61022c5481565b3480156105ab57600080fd5b506102e86105ba366004612d4d565b6116a1565b3480156105cb57600080fd5b506105df6105da3660046129e6565b611b86565b6040805182518152602092830151928101929092520161029a565b34801561060657600080fd5b506102ba6102315481565b34801561061d57600080fd5b506102e861062c3660046129e6565b611c30565b34801561063d57600080fd5b5061042961064c3660046129ff565b6102376020526000908152604090205460ff1681565b34801561066e57600080fd5b506102ba6102305481565b34801561068557600080fd5b506102ba6106943660046129ff565b611c3e565b3480156106a557600080fd5b506102e86106b43660046129e6565b611c70565b3480156106c557600080fd5b506102ba611cd0565b3480156106da57600080fd5b506102ba61022b5481565b3480156106f157600080fd5b506102ba6102325481565b34801561070857600080fd5b506102ba6102345481565b34801561071f57600080fd5b5061012e546001600160a01b03166104ed565b34801561073e57600080fd5b506102e861074d3660046129ff565b611d37565b34801561075e57600080fd5b5061022a546104ed906001600160a01b031681565b34801561077f57600080fd5b5060fb546001600160a01b03166104ed565b61023560205281600052604060002081815481106107ae57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b6107e8611d6c565b6107f0611dc7565b336107fa81611e11565b156108205760405162461bcd60e51b815260040161081790612d6f565b60405180910390fd5b600083116108405760405162461bcd60e51b815260040161081790612d8b565b61022d5461085090600190612dc5565b8260ff16111561089b5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081cdd185ada5b99c81c195c9a5bd960521b6044820152606401610817565b6108a6600080611e84565b600061022d8360ff16815481106108bf576108bf612dd8565b600091825260208083206040805180820182526002909402909101805484526001015483830152805160a08101909152878152825192945091908201906109069042612dee565b815283516020820152610232546040820152600060609091015261022b5483519192501180159061093a575061022c548510155b1561095b5733600090815261023760205260409020805460ff191660011790555b3360008181526102356020908152604080832080546001808201835582865284862088516005909302019182559387015181850155918601516002830155606086015160038301556080860151600490920191909155928252915490916109c191612dc5565b905060006127108460200151886109d89190612e01565b6109e29190612e18565b90508061023460008282546109f79190612dee565b92505081905550866102336000828254610a119190612dee565b909155505061022a54610a2f906001600160a01b031633308a611f49565b604080518381526020810189905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910160405180910390a25050505050610a7a60016101f855565b5050565b610a86611d6c565b33610a9081611e11565b15610aad5760405162461bcd60e51b815260040161081790612d6f565b610ab8826001612dee565b33600090815261023560205260409020541015610ae75760405162461bcd60e51b815260040161081790612e3a565b610af2335b83611e84565b610afc3383611fba565b50610b0860016101f855565b50565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b535760405162461bcd60e51b815260040161081790612e66565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b856120bb565b6001600160a01b031614610bab5760405162461bcd60e51b815260040161081790612eb2565b610bb4816120d7565b60408051600080825260208201909252610b08918391906120df565b610bd861224a565b600061022e5411610c2b5760405162461bcd60e51b815260206004820152601b60248201527f72657761726473206475726174696f6e206973206e6f742073657400000000006044820152606401610817565b60008111610c4b5760405162461bcd60e51b815260040161081790612d8b565b610c56600080611e84565b61022f544210610c775761022e54610c6e9082612e18565b61023155610cb7565b6000610231544261022f54610c8c9190612dc5565b610c969190612e01565b61022e54909150610ca78284612dee565b610cb19190612e18565b61023155505b60006102315411610cfc5760405162461bcd60e51b815260206004820152600f60248201526e07265776172642072617465203d203608c1b6044820152606401610817565b61022e546102335461022a546040516370a0823160e01b815284916001600160a01b0316906370a0823190610d35903090600401612ccb565b602060405180830381865afa158015610d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d769190612efe565b610d809190612dee565b610d8a9190612dc5565b610d949190612e18565b610231541115610de05760405162461bcd60e51b815260206004820152601760248201527672657761726420616d6f756e74203e2062616c616e636560481b6044820152606401610817565b61022e54610dee9042612dee565b61022f5542610230556102368054829190600090610e0d908490612dee565b909155505061022a54610e2b906001600160a01b0316333084611f49565b610231546040805183815260208101929092527fc3ed9e2a55e03c1173986e2799c70b4a5654ed43739f79f1ad3833683dad9f7f910160405180910390a150565b6001600160a01b038216600090815261023560205260408120805482919084908110610e9a57610e9a612dd8565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000610ef682604001516122a9565b90506000612710828460000151610f0d9190612e01565b610f179190612e18565b90506000670de0b6b3a76400008460600151610f31611cd0565b610f3b9190612dc5565b610f459084612e01565b610f4f9190612e18565b9050836080015181610f619190612dee565b9450505050505b92915050565b610f7661224a565b61022b55565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610fc45760405162461bcd60e51b815260040161081790612e66565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ff66120bb565b6001600160a01b03161461101c5760405162461bcd60e51b815260040161081790612eb2565b611025826120d7565b610a7a828260016120df565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110cc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610817565b5060008051602061304483398151915290565b61022d81815481106110f057600080fd5b60009182526020909120600290910201805460019091015490915082565b61012e5460408051635c975abb60e01b815290516000926001600160a01b031691635c975abb9160048083019260209291908290030181865afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612f17565b905090565b600054610100900460ff16158080156111a25750600054600160ff909116105b806111bc5750303b1580156111bc575060005460ff166001145b61121f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610817565b6000805460ff191660011790558015611242576000805461ff0019166101001790555b61124d888888612333565b61022a80546001600160a01b0319166001600160a01b038716179055835160005b818110156112cc5761022d86828151811061128b5761128b612dd8565b6020908102919091018101518254600181810185556000948552938390208251600290920201908155910151910155806112c481612f39565b91505061126e565b505061022b83905561022c8290558015611320576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b61133261224a565b60405162461bcd60e51b81526020600482015260036024820152624c363560e81b6044820152606401610817565b61136861224a565b61022d805460018101825560009190915281517fcbe5eb94ee31c6183f3d82fc7ed725908f7d7e2da0ee28e8d5e09973be5efd3d6002909202918201556020909101517fcbe5eb94ee31c6183f3d82fc7ed725908f7d7e2da0ee28e8d5e09973be5efd3e90910155565b6001600160a01b038116600090815261023560205260408120546060918167ffffffffffffffff81111561140857611408612a1c565b604051908082528060200260200182016040528015611431578160200160208202803683370190505b50905060005b82811015611478576114498582610e6c565b82828151811061145b5761145b612dd8565b60209081029190910101528061147081612f39565b915050611437565b509392505050565b600061117d61022f544261238d565b6001600160a01b038116600090815261023560209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561152c57838290600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050815260200190600101906114c8565b505050509050919050565b61153f61224a565b600081116115755760405162461bcd60e51b815260206004820152600360248201526204c31360ec1b6044820152606401610817565b6040516370a0823160e01b8152829082906001600160a01b038316906370a08231906115a5903090600401612ccb565b602060405180830381865afa1580156115c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e69190612efe565b101561161a5760405162461bcd60e51b81526020600482015260036024820152624c313160e81b6044820152606401610817565b61162e6001600160a01b03821633846123a6565b505050565b60fb5460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa15801561167d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612f52565b6116a9611d6c565b336116b381611e11565b156116d05760405162461bcd60e51b815260040161081790612d6f565b600083116116f05760405162461bcd60e51b815260040161081790612d8b565b6116fb826001612dee565b3360009081526102356020526040902054101561172a5760405162461bcd60e51b815260040161081790612e3a565b3360009081526102356020526040902080548390811061174c5761174c612dd8565b9060005260206000209060050201600101544210156117b95760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f7420756e7374616b6520647572696e67207374616b696e672070656044820152631c9a5bd960e21b6064820152608401610817565b336000908152610235602052604090208054839081106117db576117db612dd8565b90600052602060002090600502016000015483111561183c5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e7420756e7374616b6520616d6f756e7400000000006044820152606401610817565b61184533610aec565b33600090815261023560205260408120805461188391908590811061186c5761186c612dd8565b9060005260206000209060050201600201546122a9565b905060006127106118948387612e01565b61189e9190612e18565b90508061023460008282546118b39190612dc5565b925050819055508461023360008282546118cd9190612dc5565b9091555050336000908152610235602052604090208054869190869081106118f7576118f7612dd8565b906000526020600020906005020160000160008282546119179190612dc5565b909155505061022b543360009081526102356020526040902080548690811061194257611942612dd8565b90600052602060002090600502016002015410158015611997575061022c543360009081526102356020526040902080548690811061198357611983612dd8565b906000526020600020906005020160000154105b156119b55733600090815261023760205260409020805460ff191690555b336000908152610235602052604090208054859081106119d7576119d7612dd8565b906000526020600020906005020160000154600003611b25576119fa3385611fba565b336000908152610235602052604090208054611a1890600190612dc5565b81548110611a2857611a28612dd8565b90600052602060002090600502016102356000611a423390565b6001600160a01b03166001600160a01b031681526020019081526020016000208581548110611a7357611a73612dd8565b906000526020600020906005020160008201548160000155600182015481600101556002820154816002015560038201548160030155600482015481600401559050506102356000611ac23390565b6001600160a01b03166001600160a01b03168152602001908152602001600020805480611af157611af1612f6f565b6000828152602081206005600019909301928302018181556001810182905560028101829055600381018290556004015590555b611b3d3361022a546001600160a01b031690876123a6565b604080518581526020810187905233917f7fc4727e062e336010f2c282598ef5f14facb3de68cf8195c2f23e1454b2b74e910160405180910390a2505050610a7a60016101f855565b604080518082019091526000808252602082015261022d548290611bac90600190612dc5565b1015611be85760405162461bcd60e51b815260206004820152600b60248201526a0eee4dedcce40d2dcc8caf60ab1b6044820152606401610817565b61022d8281548110611bfc57611bfc612dd8565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250509050919050565b611c3861224a565b61022c55565b6001600160a01b0381166000908152610237602052604081205460ff1615611c6857506003919050565b506000919050565b611c7861224a565b4261022f5410611cca5760405162461bcd60e51b815260206004820152601f60248201527f726577617264206475726174696f6e206973206e6f742066696e6973686564006044820152606401610817565b61022e55565b600061023354600003611ce557506102325490565b6102345461023054611cf5611480565b611cff9190612dc5565b61023154611d0d9190612e01565b611d1f90670de0b6b3a7640000612e01565b611d299190612e18565b6102325461117d9190612dee565b611d3f61224a565b60405162461bcd60e51b8152602060048201526002602482015261098760f31b6044820152606401610817565b60026101f85403611dbf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610817565b60026101f855565b611dcf61110e565b15611e0f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610817565b565b6101615460405163fe575a8760e01b81526000916001600160a01b03169063fe575a8790611e43908590600401612ccb565b602060405180830381865afa158015611e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f689190612f17565b611e8c611cd0565b61023255611e98611480565b610230556001600160a01b03821615610a7a57611eb58282610e6c565b6001600160a01b038316600090815261023560205260409020805483908110611ee057611ee0612dd8565b906000526020600020906005020160040181905550610232546102356000846001600160a01b03166001600160a01b031681526020019081526020016000208281548110611f3057611f30612dd8565b9060005260206000209060050201600301819055505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611fb49085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526123d6565b50505050565b6001600160a01b038216600090815261023560205260408120805483908110611fe557611fe5612dd8565b9060005260206000209060050201600401549050600081111561162e576001600160a01b03831660009081526102356020526040812080548490811061202d5761202d612dd8565b9060005260206000209060050201600401819055508061023660008282546120559190612dc5565b909155505061022a54612072906001600160a01b031684836123a6565b60408051838152602081018390526001600160a01b038516917fd6f2c8500df5b44f11e9e48b91ff9f1b9d81bc496d55570c2b1b75bf65243f51910160405180910390a2505050565b600080516020613044833981519152546001600160a01b031690565b610b0861224a565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156121125761162e836124ab565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561216c575060408051601f3d908101601f1916820190925261216991810190612efe565b60015b6121cf5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610817565b600080516020613044833981519152811461223e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610817565b5061162e838383612547565b33612253611633565b6001600160a01b031614611e0f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b61022d54600090815b8181101561232957600061022d82815481106122d0576122d0612dd8565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250509050806000015185036123165760200151949350505050565b508061232181612f39565b9150506122b2565b5060009392505050565b600054610100900460ff1661235a5760405162461bcd60e51b815260040161081790612f85565b61236261256c565b61236b83612593565b6123736125c3565b61237c826125f2565b6123858161263c565b61162e61256c565b60008183111561239d578161239f565b825b9392505050565b6040516001600160a01b03831660248201526044810182905261162e90849063a9059cbb60e01b90606401611f7d565b600061242b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166126869092919063ffffffff16565b905080516000148061244c57508080602001905181019061244c9190612f17565b61162e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610817565b6001600160a01b0381163b6125185760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610817565b60008051602061304483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6125508361269d565b60008251118061255d5750805b1561162e57611fb483836126dd565b600054610100900460ff16611e0f5760405162461bcd60e51b815260040161081790612f85565b600054610100900460ff166125ba5760405162461bcd60e51b815260040161081790612f85565b610b0881612702565b600054610100900460ff166125ea5760405162461bcd60e51b815260040161081790612f85565b611e0f61274b565b600054610100900460ff166126195760405162461bcd60e51b815260040161081790612f85565b61012e80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166126635760405162461bcd60e51b815260040161081790612f85565b61016180546001600160a01b0319166001600160a01b0392909216919091179055565b6060612695848460008561277e565b949350505050565b6126a6816124ab565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061239f838360405180606001604052806027815260200161306460279139612859565b600054610100900460ff166127295760405162461bcd60e51b815260040161081790612f85565b60fb80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166127725760405162461bcd60e51b815260040161081790612f85565b6097805460ff19169055565b6060824710156127df5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610817565b600080866001600160a01b031685876040516127fb9190612ff4565b60006040518083038185875af1925050503d8060008114612838576040519150601f19603f3d011682016040523d82523d6000602084013e61283d565b606091505b509150915061284e878383876128d1565b979650505050505050565b6060600080856001600160a01b0316856040516128769190612ff4565b600060405180830381855af49150503d80600081146128b1576040519150601f19603f3d011682016040523d82523d6000602084013e6128b6565b606091505b50915091506128c7868383876128d1565b9695505050505050565b60608315612940578251600003612939576001600160a01b0385163b6129395760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610817565b5081612695565b61269583838151156129555781518083602001fd5b8060405162461bcd60e51b81526004016108179190613010565b6001600160a01b0381168114610b0857600080fd5b6000806040838503121561299757600080fd5b82356129a28161296f565b946020939093013593505050565b600080604083850312156129c357600080fd5b82359150602083013560ff811681146129db57600080fd5b809150509250929050565b6000602082840312156129f857600080fd5b5035919050565b600060208284031215612a1157600080fd5b813561239f8161296f565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a5b57612a5b612a1c565b604052919050565b60008060408385031215612a7657600080fd5b8235612a818161296f565b915060208381013567ffffffffffffffff80821115612a9f57600080fd5b818601915086601f830112612ab357600080fd5b813581811115612ac557612ac5612a1c565b612ad7601f8201601f19168501612a32565b91508082528784828501011115612aed57600080fd5b80848401858401376000848284010152508093505050509250929050565b600060408284031215612b1d57600080fd5b6040516040810181811067ffffffffffffffff82111715612b4057612b40612a1c565b604052823581526020928301359281019290925250919050565b600080600080600080600060e0888a031215612b7557600080fd5b8735612b808161296f565b9650602088810135612b918161296f565b9650604089810135612ba28161296f565b965060608a0135612bb28161296f565b955060808a013567ffffffffffffffff80821115612bcf57600080fd5b818c0191508c601f830112612be357600080fd5b813581811115612bf557612bf5612a1c565b612c03858260051b01612a32565b818152858101925060069190911b83018501908e821115612c2357600080fd5b928501925b81841015612c4957612c3a8f85612b0b565b83529284019291850191612c28565b9b9e9a9d50989b979a9960a0890135995060c090980135979650505050505050565b600060408284031215612c7d57600080fd5b61239f8383612b0b565b6020808252825182820181905260009190848201906040850190845b81811015612cbf57835183529284019291840191600101612ca3565b50909695505050505050565b6001600160a01b0391909116815260200190565b602080825282518282018190526000919060409081850190868401855b82811015612d405781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101612cfc565b5091979650505050505050565b60008060408385031215612d6057600080fd5b50508035926020909101359150565b6020808252600290820152614c3960f01b604082015260600190565b6020808252600a90820152690616d6f756e74203d20360b41b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f6857610f68612daf565b634e487b7160e01b600052603260045260246000fd5b80820180821115610f6857610f68612daf565b8082028115828204841417610f6857610f68612daf565b600082612e3557634e487b7160e01b600052601260045260246000fd5b500490565b602080825260129082015271092dcecc2d8d2c840e6e8c2d6ca92dcc8caf60731b604082015260600190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b600060208284031215612f1057600080fd5b5051919050565b600060208284031215612f2957600080fd5b8151801515811461239f57600080fd5b600060018201612f4b57612f4b612daf565b5060010190565b600060208284031215612f6457600080fd5b815161239f8161296f565b634e487b7160e01b600052603160045260246000fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60005b83811015612feb578181015183820152602001612fd3565b50506000910152565b60008251613006818460208701612fd0565b9190910192915050565b602081526000825180602084015261302f816040850160208701612fd0565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220dd8f5718c929011317fcd87e89f5583d4a3d3bab40cf01666a792f08e3afe72d64736f6c63430008120033", + "deployedBytecode": "0x6080604052600436106102515760003560e01c8063817b1cd211610139578063c8f33c91116100b6578063df136d651161007a578063df136d65146106e5578063eed9da1f146106fc578063f12d54d814610713578063f2fde38b14610732578063f6c3565014610752578063f762e7341461077357600080fd5b8063c8f33c9114610662578063c8f74bb814610679578063cc1a378f14610699578063cd3daf9d146106b9578063cedaf639146106ce57600080fd5b80639e2c8a5b116100fd5780639e2c8a5b1461059f578063a029e898146105bf578063bddff592146105fa578063be01d6c714610611578063c66120f41461063157600080fd5b8063817b1cd21461050f578063842e2981146105265780638980f11f146105535780638da5cb5b146105735780639b602f0a1461058857600080fd5b80634f1ef286116101d257806367d3b4881161019657806367d3b48814610459578063715018a614610470578063793e875e146104855780637b2cca38146104a55780637c2edb16146104d257806380faa57d146104fa57600080fd5b80634f1ef286146103b757806352d1902d146103ca5780635c046e66146103df5780635c975abb1461041457806363d071201461043957600080fd5b8063386a952511610219578063386a95251461032a5780633c6b16ab146103415780633e491d471461036157806340a8d39f146103815780634a7f48041461039757600080fd5b806304d978f1146102565780630e15561a146102a357806310087fb1146102c85780631c4b774b146102ea5780633659cfe61461030a575b600080fd5b34801561026257600080fd5b50610276610271366004612984565b610791565b604080519586526020860194909452928401919091526060830152608082015260a0015b60405180910390f35b3480156102af57600080fd5b506102ba6102365481565b60405190815260200161029a565b3480156102d457600080fd5b506102e86102e33660046129b0565b6107e0565b005b3480156102f657600080fd5b506102e86103053660046129e6565b610a7e565b34801561031657600080fd5b506102e86103253660046129ff565b610b0b565b34801561033657600080fd5b506102ba61022e5481565b34801561034d57600080fd5b506102e861035c3660046129e6565b610bd0565b34801561036d57600080fd5b506102ba61037c366004612984565b610e6c565b34801561038d57600080fd5b506102ba61271081565b3480156103a357600080fd5b506102e86103b23660046129e6565b610f6e565b6102e86103c5366004612a63565b610f7c565b3480156103d657600080fd5b506102ba611031565b3480156103eb57600080fd5b506103ff6103fa3660046129e6565b6110df565b6040805192835260208301919091520161029a565b34801561042057600080fd5b5061042961110e565b604051901515815260200161029a565b34801561044557600080fd5b506102e8610454366004612b5a565b611182565b34801561046557600080fd5b506102ba61022f5481565b34801561047c57600080fd5b506102e861132a565b34801561049157600080fd5b506102e86104a0366004612c6b565b611360565b3480156104b157600080fd5b506104c56104c03660046129ff565b6113d2565b60405161029a9190612c87565b3480156104de57600080fd5b50610161546001600160a01b03165b60405161029a9190612ccb565b34801561050657600080fd5b506102ba611480565b34801561051b57600080fd5b506102ba6102335481565b34801561053257600080fd5b506105466105413660046129ff565b61148f565b60405161029a9190612cdf565b34801561055f57600080fd5b506102e861056e366004612984565b611537565b34801561057f57600080fd5b506104ed611633565b34801561059457600080fd5b506102ba61022c5481565b3480156105ab57600080fd5b506102e86105ba366004612d4d565b6116a1565b3480156105cb57600080fd5b506105df6105da3660046129e6565b611b86565b6040805182518152602092830151928101929092520161029a565b34801561060657600080fd5b506102ba6102315481565b34801561061d57600080fd5b506102e861062c3660046129e6565b611c30565b34801561063d57600080fd5b5061042961064c3660046129ff565b6102376020526000908152604090205460ff1681565b34801561066e57600080fd5b506102ba6102305481565b34801561068557600080fd5b506102ba6106943660046129ff565b611c3e565b3480156106a557600080fd5b506102e86106b43660046129e6565b611c70565b3480156106c557600080fd5b506102ba611cd0565b3480156106da57600080fd5b506102ba61022b5481565b3480156106f157600080fd5b506102ba6102325481565b34801561070857600080fd5b506102ba6102345481565b34801561071f57600080fd5b5061012e546001600160a01b03166104ed565b34801561073e57600080fd5b506102e861074d3660046129ff565b611d37565b34801561075e57600080fd5b5061022a546104ed906001600160a01b031681565b34801561077f57600080fd5b5060fb546001600160a01b03166104ed565b61023560205281600052604060002081815481106107ae57600080fd5b600091825260209091206005909102018054600182015460028301546003840154600490940154929550909350919085565b6107e8611d6c565b6107f0611dc7565b336107fa81611e11565b156108205760405162461bcd60e51b815260040161081790612d6f565b60405180910390fd5b600083116108405760405162461bcd60e51b815260040161081790612d8b565b61022d5461085090600190612dc5565b8260ff16111561089b5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081cdd185ada5b99c81c195c9a5bd960521b6044820152606401610817565b6108a6600080611e84565b600061022d8360ff16815481106108bf576108bf612dd8565b600091825260208083206040805180820182526002909402909101805484526001015483830152805160a08101909152878152825192945091908201906109069042612dee565b815283516020820152610232546040820152600060609091015261022b5483519192501180159061093a575061022c548510155b1561095b5733600090815261023760205260409020805460ff191660011790555b3360008181526102356020908152604080832080546001808201835582865284862088516005909302019182559387015181850155918601516002830155606086015160038301556080860151600490920191909155928252915490916109c191612dc5565b905060006127108460200151886109d89190612e01565b6109e29190612e18565b90508061023460008282546109f79190612dee565b92505081905550866102336000828254610a119190612dee565b909155505061022a54610a2f906001600160a01b031633308a611f49565b604080518381526020810189905233917f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee90910160405180910390a25050505050610a7a60016101f855565b5050565b610a86611d6c565b33610a9081611e11565b15610aad5760405162461bcd60e51b815260040161081790612d6f565b610ab8826001612dee565b33600090815261023560205260409020541015610ae75760405162461bcd60e51b815260040161081790612e3a565b610af2335b83611e84565b610afc3383611fba565b50610b0860016101f855565b50565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b535760405162461bcd60e51b815260040161081790612e66565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b856120bb565b6001600160a01b031614610bab5760405162461bcd60e51b815260040161081790612eb2565b610bb4816120d7565b60408051600080825260208201909252610b08918391906120df565b610bd861224a565b600061022e5411610c2b5760405162461bcd60e51b815260206004820152601b60248201527f72657761726473206475726174696f6e206973206e6f742073657400000000006044820152606401610817565b60008111610c4b5760405162461bcd60e51b815260040161081790612d8b565b610c56600080611e84565b61022f544210610c775761022e54610c6e9082612e18565b61023155610cb7565b6000610231544261022f54610c8c9190612dc5565b610c969190612e01565b61022e54909150610ca78284612dee565b610cb19190612e18565b61023155505b60006102315411610cfc5760405162461bcd60e51b815260206004820152600f60248201526e07265776172642072617465203d203608c1b6044820152606401610817565b61022e546102335461022a546040516370a0823160e01b815284916001600160a01b0316906370a0823190610d35903090600401612ccb565b602060405180830381865afa158015610d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d769190612efe565b610d809190612dee565b610d8a9190612dc5565b610d949190612e18565b610231541115610de05760405162461bcd60e51b815260206004820152601760248201527672657761726420616d6f756e74203e2062616c616e636560481b6044820152606401610817565b61022e54610dee9042612dee565b61022f5542610230556102368054829190600090610e0d908490612dee565b909155505061022a54610e2b906001600160a01b0316333084611f49565b610231546040805183815260208101929092527fc3ed9e2a55e03c1173986e2799c70b4a5654ed43739f79f1ad3833683dad9f7f910160405180910390a150565b6001600160a01b038216600090815261023560205260408120805482919084908110610e9a57610e9a612dd8565b90600052602060002090600502016040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000610ef682604001516122a9565b90506000612710828460000151610f0d9190612e01565b610f179190612e18565b90506000670de0b6b3a76400008460600151610f31611cd0565b610f3b9190612dc5565b610f459084612e01565b610f4f9190612e18565b9050836080015181610f619190612dee565b9450505050505b92915050565b610f7661224a565b61022b55565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610fc45760405162461bcd60e51b815260040161081790612e66565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ff66120bb565b6001600160a01b03161461101c5760405162461bcd60e51b815260040161081790612eb2565b611025826120d7565b610a7a828260016120df565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110cc5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610817565b5060008051602061304483398151915290565b61022d81815481106110f057600080fd5b60009182526020909120600290910201805460019091015490915082565b61012e5460408051635c975abb60e01b815290516000926001600160a01b031691635c975abb9160048083019260209291908290030181865afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612f17565b905090565b600054610100900460ff16158080156111a25750600054600160ff909116105b806111bc5750303b1580156111bc575060005460ff166001145b61121f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610817565b6000805460ff191660011790558015611242576000805461ff0019166101001790555b61124d888888612333565b61022a80546001600160a01b0319166001600160a01b038716179055835160005b818110156112cc5761022d86828151811061128b5761128b612dd8565b6020908102919091018101518254600181810185556000948552938390208251600290920201908155910151910155806112c481612f39565b91505061126e565b505061022b83905561022c8290558015611320576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b61133261224a565b60405162461bcd60e51b81526020600482015260036024820152624c363560e81b6044820152606401610817565b61136861224a565b61022d805460018101825560009190915281517fcbe5eb94ee31c6183f3d82fc7ed725908f7d7e2da0ee28e8d5e09973be5efd3d6002909202918201556020909101517fcbe5eb94ee31c6183f3d82fc7ed725908f7d7e2da0ee28e8d5e09973be5efd3e90910155565b6001600160a01b038116600090815261023560205260408120546060918167ffffffffffffffff81111561140857611408612a1c565b604051908082528060200260200182016040528015611431578160200160208202803683370190505b50905060005b82811015611478576114498582610e6c565b82828151811061145b5761145b612dd8565b60209081029190910101528061147081612f39565b915050611437565b509392505050565b600061117d61022f544261238d565b6001600160a01b038116600090815261023560209081526040808320805482518185028101850190935280835260609492939192909184015b8282101561152c57838290600052602060002090600502016040518060a001604052908160008201548152602001600182015481526020016002820154815260200160038201548152602001600482015481525050815260200190600101906114c8565b505050509050919050565b61153f61224a565b600081116115755760405162461bcd60e51b815260206004820152600360248201526204c31360ec1b6044820152606401610817565b6040516370a0823160e01b8152829082906001600160a01b038316906370a08231906115a5903090600401612ccb565b602060405180830381865afa1580156115c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e69190612efe565b101561161a5760405162461bcd60e51b81526020600482015260036024820152624c313160e81b6044820152606401610817565b61162e6001600160a01b03821633846123a6565b505050565b60fb5460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa15801561167d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612f52565b6116a9611d6c565b336116b381611e11565b156116d05760405162461bcd60e51b815260040161081790612d6f565b600083116116f05760405162461bcd60e51b815260040161081790612d8b565b6116fb826001612dee565b3360009081526102356020526040902054101561172a5760405162461bcd60e51b815260040161081790612e3a565b3360009081526102356020526040902080548390811061174c5761174c612dd8565b9060005260206000209060050201600101544210156117b95760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f7420756e7374616b6520647572696e67207374616b696e672070656044820152631c9a5bd960e21b6064820152608401610817565b336000908152610235602052604090208054839081106117db576117db612dd8565b90600052602060002090600502016000015483111561183c5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e7420756e7374616b6520616d6f756e7400000000006044820152606401610817565b61184533610aec565b33600090815261023560205260408120805461188391908590811061186c5761186c612dd8565b9060005260206000209060050201600201546122a9565b905060006127106118948387612e01565b61189e9190612e18565b90508061023460008282546118b39190612dc5565b925050819055508461023360008282546118cd9190612dc5565b9091555050336000908152610235602052604090208054869190869081106118f7576118f7612dd8565b906000526020600020906005020160000160008282546119179190612dc5565b909155505061022b543360009081526102356020526040902080548690811061194257611942612dd8565b90600052602060002090600502016002015410158015611997575061022c543360009081526102356020526040902080548690811061198357611983612dd8565b906000526020600020906005020160000154105b156119b55733600090815261023760205260409020805460ff191690555b336000908152610235602052604090208054859081106119d7576119d7612dd8565b906000526020600020906005020160000154600003611b25576119fa3385611fba565b336000908152610235602052604090208054611a1890600190612dc5565b81548110611a2857611a28612dd8565b90600052602060002090600502016102356000611a423390565b6001600160a01b03166001600160a01b031681526020019081526020016000208581548110611a7357611a73612dd8565b906000526020600020906005020160008201548160000155600182015481600101556002820154816002015560038201548160030155600482015481600401559050506102356000611ac23390565b6001600160a01b03166001600160a01b03168152602001908152602001600020805480611af157611af1612f6f565b6000828152602081206005600019909301928302018181556001810182905560028101829055600381018290556004015590555b611b3d3361022a546001600160a01b031690876123a6565b604080518581526020810187905233917f7fc4727e062e336010f2c282598ef5f14facb3de68cf8195c2f23e1454b2b74e910160405180910390a2505050610a7a60016101f855565b604080518082019091526000808252602082015261022d548290611bac90600190612dc5565b1015611be85760405162461bcd60e51b815260206004820152600b60248201526a0eee4dedcce40d2dcc8caf60ab1b6044820152606401610817565b61022d8281548110611bfc57611bfc612dd8565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250509050919050565b611c3861224a565b61022c55565b6001600160a01b0381166000908152610237602052604081205460ff1615611c6857506003919050565b506000919050565b611c7861224a565b4261022f5410611cca5760405162461bcd60e51b815260206004820152601f60248201527f726577617264206475726174696f6e206973206e6f742066696e6973686564006044820152606401610817565b61022e55565b600061023354600003611ce557506102325490565b6102345461023054611cf5611480565b611cff9190612dc5565b61023154611d0d9190612e01565b611d1f90670de0b6b3a7640000612e01565b611d299190612e18565b6102325461117d9190612dee565b611d3f61224a565b60405162461bcd60e51b8152602060048201526002602482015261098760f31b6044820152606401610817565b60026101f85403611dbf5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610817565b60026101f855565b611dcf61110e565b15611e0f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610817565b565b6101615460405163fe575a8760e01b81526000916001600160a01b03169063fe575a8790611e43908590600401612ccb565b602060405180830381865afa158015611e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f689190612f17565b611e8c611cd0565b61023255611e98611480565b610230556001600160a01b03821615610a7a57611eb58282610e6c565b6001600160a01b038316600090815261023560205260409020805483908110611ee057611ee0612dd8565b906000526020600020906005020160040181905550610232546102356000846001600160a01b03166001600160a01b031681526020019081526020016000208281548110611f3057611f30612dd8565b9060005260206000209060050201600301819055505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611fb49085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526123d6565b50505050565b6001600160a01b038216600090815261023560205260408120805483908110611fe557611fe5612dd8565b9060005260206000209060050201600401549050600081111561162e576001600160a01b03831660009081526102356020526040812080548490811061202d5761202d612dd8565b9060005260206000209060050201600401819055508061023660008282546120559190612dc5565b909155505061022a54612072906001600160a01b031684836123a6565b60408051838152602081018390526001600160a01b038516917fd6f2c8500df5b44f11e9e48b91ff9f1b9d81bc496d55570c2b1b75bf65243f51910160405180910390a2505050565b600080516020613044833981519152546001600160a01b031690565b610b0861224a565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156121125761162e836124ab565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561216c575060408051601f3d908101601f1916820190925261216991810190612efe565b60015b6121cf5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610817565b600080516020613044833981519152811461223e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610817565b5061162e838383612547565b33612253611633565b6001600160a01b031614611e0f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610817565b61022d54600090815b8181101561232957600061022d82815481106122d0576122d0612dd8565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250509050806000015185036123165760200151949350505050565b508061232181612f39565b9150506122b2565b5060009392505050565b600054610100900460ff1661235a5760405162461bcd60e51b815260040161081790612f85565b61236261256c565b61236b83612593565b6123736125c3565b61237c826125f2565b6123858161263c565b61162e61256c565b60008183111561239d578161239f565b825b9392505050565b6040516001600160a01b03831660248201526044810182905261162e90849063a9059cbb60e01b90606401611f7d565b600061242b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166126869092919063ffffffff16565b905080516000148061244c57508080602001905181019061244c9190612f17565b61162e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610817565b6001600160a01b0381163b6125185760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610817565b60008051602061304483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6125508361269d565b60008251118061255d5750805b1561162e57611fb483836126dd565b600054610100900460ff16611e0f5760405162461bcd60e51b815260040161081790612f85565b600054610100900460ff166125ba5760405162461bcd60e51b815260040161081790612f85565b610b0881612702565b600054610100900460ff166125ea5760405162461bcd60e51b815260040161081790612f85565b611e0f61274b565b600054610100900460ff166126195760405162461bcd60e51b815260040161081790612f85565b61012e80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166126635760405162461bcd60e51b815260040161081790612f85565b61016180546001600160a01b0319166001600160a01b0392909216919091179055565b6060612695848460008561277e565b949350505050565b6126a6816124ab565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061239f838360405180606001604052806027815260200161306460279139612859565b600054610100900460ff166127295760405162461bcd60e51b815260040161081790612f85565b60fb80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166127725760405162461bcd60e51b815260040161081790612f85565b6097805460ff19169055565b6060824710156127df5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610817565b600080866001600160a01b031685876040516127fb9190612ff4565b60006040518083038185875af1925050503d8060008114612838576040519150601f19603f3d011682016040523d82523d6000602084013e61283d565b606091505b509150915061284e878383876128d1565b979650505050505050565b6060600080856001600160a01b0316856040516128769190612ff4565b600060405180830381855af49150503d80600081146128b1576040519150601f19603f3d011682016040523d82523d6000602084013e6128b6565b606091505b50915091506128c7868383876128d1565b9695505050505050565b60608315612940578251600003612939576001600160a01b0385163b6129395760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610817565b5081612695565b61269583838151156129555781518083602001fd5b8060405162461bcd60e51b81526004016108179190613010565b6001600160a01b0381168114610b0857600080fd5b6000806040838503121561299757600080fd5b82356129a28161296f565b946020939093013593505050565b600080604083850312156129c357600080fd5b82359150602083013560ff811681146129db57600080fd5b809150509250929050565b6000602082840312156129f857600080fd5b5035919050565b600060208284031215612a1157600080fd5b813561239f8161296f565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a5b57612a5b612a1c565b604052919050565b60008060408385031215612a7657600080fd5b8235612a818161296f565b915060208381013567ffffffffffffffff80821115612a9f57600080fd5b818601915086601f830112612ab357600080fd5b813581811115612ac557612ac5612a1c565b612ad7601f8201601f19168501612a32565b91508082528784828501011115612aed57600080fd5b80848401858401376000848284010152508093505050509250929050565b600060408284031215612b1d57600080fd5b6040516040810181811067ffffffffffffffff82111715612b4057612b40612a1c565b604052823581526020928301359281019290925250919050565b600080600080600080600060e0888a031215612b7557600080fd5b8735612b808161296f565b9650602088810135612b918161296f565b9650604089810135612ba28161296f565b965060608a0135612bb28161296f565b955060808a013567ffffffffffffffff80821115612bcf57600080fd5b818c0191508c601f830112612be357600080fd5b813581811115612bf557612bf5612a1c565b612c03858260051b01612a32565b818152858101925060069190911b83018501908e821115612c2357600080fd5b928501925b81841015612c4957612c3a8f85612b0b565b83529284019291850191612c28565b9b9e9a9d50989b979a9960a0890135995060c090980135979650505050505050565b600060408284031215612c7d57600080fd5b61239f8383612b0b565b6020808252825182820181905260009190848201906040850190845b81811015612cbf57835183529284019291840191600101612ca3565b50909695505050505050565b6001600160a01b0391909116815260200190565b602080825282518282018190526000919060409081850190868401855b82811015612d405781518051855286810151878601528581015186860152606080820151908601526080908101519085015260a09093019290850190600101612cfc565b5091979650505050505050565b60008060408385031215612d6057600080fd5b50508035926020909101359150565b6020808252600290820152614c3960f01b604082015260600190565b6020808252600a90820152690616d6f756e74203d20360b41b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f6857610f68612daf565b634e487b7160e01b600052603260045260246000fd5b80820180821115610f6857610f68612daf565b8082028115828204841417610f6857610f68612daf565b600082612e3557634e487b7160e01b600052601260045260246000fd5b500490565b602080825260129082015271092dcecc2d8d2c840e6e8c2d6ca92dcc8caf60731b604082015260600190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b600060208284031215612f1057600080fd5b5051919050565b600060208284031215612f2957600080fd5b8151801515811461239f57600080fd5b600060018201612f4b57612f4b612daf565b5060010190565b600060208284031215612f6457600080fd5b815161239f8161296f565b634e487b7160e01b600052603160045260246000fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60005b83811015612feb578181015183820152602001612fd3565b50506000910152565b60008251613006818460208701612fd0565b9190910192915050565b602081526000825180602084015261302f816040850160208701612fd0565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220dd8f5718c929011317fcd87e89f5583d4a3d3bab40cf01666a792f08e3afe72d64736f6c63430008120033", + "devdoc": { + "custom:security-contact": "security@ledgity.comsecurity@ledgity.com", + "details": "This contract implements tierOf() function from LDYStaking as it's the only one the LToken contract relies on.", + "events": { + "AdminChanged(address,address)": { + "details": "Emitted when the admin account has changed." + }, + "BeaconUpgraded(address)": { + "details": "Emitted when the beacon is changed." + }, + "Initialized(uint8)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "NotifiedRewardAmount(uint256,uint256)": { + "params": { + "rewardAmount": "Reward amount added by admin.", + "rewardPerSec": "RewardRatePerSec updated." + } + }, + "Paused(address)": { + "details": "Emitted when the pause is triggered by `account`." + }, + "RewardPaid(address,uint256,uint256)": { + "params": { + "reward": "Reward token amount", + "stakeIndex": "User staking pool index", + "user": "User address" + } + }, + "Staked(address,uint256,uint256)": { + "params": { + "amount": "Staked amount", + "stakeIndex": "Latest index of user staking pool", + "user": "User address" + } + }, + "Unpaused(address)": { + "details": "Emitted when the pause is lifted by `account`." + }, + "Unstaked(address,uint256,uint256)": { + "params": { + "amount": "Staked amount", + "stakeIndex": "User staking pool index", + "user": "User address" + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "constructor": { + "custom:oz-upgrades-unsafe-allow": "constructor" + }, + "earned(address,uint256)": { + "params": { + "account": "Address of the user.", + "stakeIndex": "Index of the stakePool" + }, + "returns": { + "_0": "Return earned amounts" + } + }, + "getEarnedUser(address)": { + "params": { + "account": "Address of the user." + }, + "returns": { + "_0": "Return earned rewards array for a user." + } + }, + "getReward(uint256)": { + "details": "Emits a `RewardPaid` event upon successful reward claim.", + "params": { + "stakeIndex": "The index of user staking pool." + } + }, + "getStakeDurationInfo(uint256)": { + "params": { + "index": "Index of StakeDurationInfos." + }, + "returns": { + "_0": "StakeDurationInfo." + } + }, + "getUserStakes(address)": { + "params": { + "account": "The address of user." + }, + "returns": { + "_0": "StakingInfo array." + } + }, + "globalBlacklist()": { + "returns": { + "_0": "The address of the GlobalBlacklist contract." + } + }, + "globalOwner()": { + "returns": { + "_0": "The address of the GlobalOwner contract." + } + }, + "globalPause()": { + "returns": { + "_0": "The address of the GlobalPause contract." + } + }, + "initialize(address,address,address,address,(uint256,uint256)[],uint256,uint256)": { + "details": "This function is intended for setting initial values for the contract's state variables.", + "params": { + "globalBlacklist_": "The address of the GlobalBlacklist contract.", + "globalOwner_": "The address of the GlobalOwner contract.", + "globalPause_": "The address of the GlobalPause contract.", + "stakeAmountForPerks_": "Minimal staking amount for perks.", + "stakeDurationForPerks_": "Minimal staking duration for perks.", + "stakeDurationInfos_": "Available Staking Durations.", + "stakeRewardToken_": "The address of stake and reward token(LDY token)." + } + }, + "lastTimeRewardApplicable()": { + "returns": { + "_0": "Timestamp of the most recent rewards calculation." + } + }, + "notifyRewardAmount(uint256)": { + "details": "Only callable by owner.", + "params": { + "amount": "The amount of reward to be distributed." + } + }, + "owner()": { + "returns": { + "_0": "The address of the owner" + } + }, + "paused()": { + "returns": { + "_0": "Whether the contract is paused or not." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "pushStakeDurationInfo((uint256,uint256))": { + "details": "Only callable by owner." + }, + "recoverERC20(address,uint256)": { + "params": { + "amount": "The amount of token to recover.", + "tokenAddress": "The address of the token to recover." + } + }, + "rewardPerToken()": { + "returns": { + "_0": "Current reward per token." + } + }, + "setRewardsDuration(uint256)": { + "details": "Only callable by owner, and setting available only after rewards period.", + "params": { + "duration": "New reward duration in seconds." + } + }, + "setStakeAmountForPerks(uint256)": { + "details": "Only callable by owner.", + "params": { + "stakeAmountForPerks_": "New stakeDurationForPerks." + } + }, + "setStakeDurationForPerks(uint256)": { + "details": "Only callable by owner.", + "params": { + "stakeDurationForPerks_": "New stakeDurationForPerks." + } + }, + "stake(uint256,uint8)": { + "details": "Emits a `Staked` event upon successful staking.", + "params": { + "amount": "The amount of tokens to stake.", + "stakeDurationIndex": "The Index of stakeDurationInfos array." + } + }, + "tierOf(address)": { + "details": "tierOf() function that always return that the given account is not elligible to any LDY staking tier, except if the account is in the highTierAccounts mapping.", + "params": { + "account": "The account to check the tier of." + } + }, + "unstake(uint256,uint256)": { + "details": "Emits a `Unstaked` event upon successful withdrawal. On full withdrawal, userStakingInfo removes stake pool for stakeIndex.", + "params": { + "amount": "The amount of tokens to withdraw.", + "stakeIndex": "The index of user staking pool" + } + }, + "upgradeTo(address)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "stateVariables": { + "highTierAccounts": { + "details": "This is notably used to allow PreMining contracts to benefit from 0% withdrawal fees in L-Tokens contracts, when accounts unlock their funds." + } + }, + "title": "LDYStaking", + "version": 1 + }, + "userdoc": { + "events": { + "NotifiedRewardAmount(uint256,uint256)": { + "notice": "Emitted when admin add rewards." + }, + "RewardPaid(address,uint256,uint256)": { + "notice": "Emitted when users claim rewards" + }, + "Staked(address,uint256,uint256)": { + "notice": "Emitted when users stake token" + }, + "Unstaked(address,uint256,uint256)": { + "notice": "Emitted when users unstake token" + } + }, + "kind": "user", + "methods": { + "MULTIPLIER_BASIS()": { + "notice": "Decimals of multiplier" + }, + "earned(address,uint256)": { + "notice": "Calculate the user's stake pool earnings" + }, + "finishAt()": { + "notice": "Timestamp of when the rewards finish." + }, + "getEarnedUser(address)": { + "notice": "Get the earned rewards array for a user." + }, + "getReward(uint256)": { + "notice": "Claim pending rewards." + }, + "getStakeDurationInfo(uint256)": { + "notice": "Get StakeDurationInfo." + }, + "getUserStakes(address)": { + "notice": "Get User Stake Data." + }, + "globalBlacklist()": { + "notice": "Retrieves the address of GlobalBlacklist contract." + }, + "globalOwner()": { + "notice": "Retrieves the address of GlobalOwner contract." + }, + "globalPause()": { + "notice": "Retrieves the address of GlobalPause contract." + }, + "highTierAccounts(address)": { + "notice": "Holds a mapping of addresses that default to the highest staking tier." + }, + "initialize(address,address,address,address,(uint256,uint256)[],uint256,uint256)": { + "notice": "Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once." + }, + "lastTimeRewardApplicable()": { + "notice": "Get the last time when rewards were applicable for the specified reward token." + }, + "lastUpdateTime()": { + "notice": "Timestamp of the reward updated." + }, + "notifyRewardAmount(uint256)": { + "notice": "Notify the contract about the amount of rewards to be distributed and update reward parameters." + }, + "owner()": { + "notice": "Override of OwnableUpgradeable.owner() that retrieves the owner's address from the GlobalOwner contract instead." + }, + "paused()": { + "notice": "Override of PausableUpgradeable.pause() that retrieves the pause state from the GlobalPause contract instead." + }, + "pushStakeDurationInfo((uint256,uint256))": { + "notice": "Push stakeDurationInfo" + }, + "recoverERC20(address,uint256)": { + "notice": "Recovers a specified amount of a given token address. Will fail if the contract doesn't hold enough tokens." + }, + "renounceOwnership()": { + "notice": "Override of OwnableUpgradeable.renounceOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there." + }, + "rewardPerToken()": { + "notice": "Calculate the reward per token for a given reward token." + }, + "rewardPerTokenStored()": { + "notice": "Reward per token stored, sum of (reward rate * dt * 1e18 / total supply)." + }, + "rewardRatePerSec()": { + "notice": "Reward per second(total rewards / duration)." + }, + "rewardsDuration()": { + "notice": "Duration of the rewards (in seconds)." + }, + "setRewardsDuration(uint256)": { + "notice": "Update Rewards Duration." + }, + "setStakeAmountForPerks(uint256)": { + "notice": "Update stakeAmountForPerks" + }, + "setStakeDurationForPerks(uint256)": { + "notice": "Update stakeDurationForPerks" + }, + "stake(uint256,uint8)": { + "notice": "Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards." + }, + "stakeAmountForPerks()": { + "notice": "Minimal stake amount for perks." + }, + "stakeDurationForPerks()": { + "notice": "Minimal stake duration for perks." + }, + "stakeDurationInfos(uint256)": { + "notice": "Stake durations info array." + }, + "stakeRewardToken()": { + "notice": "Stake and Reward token." + }, + "totalRewards()": { + "notice": "Total rewards amount." + }, + "totalStaked()": { + "notice": "Total staked amounts." + }, + "transferOwnership(address)": { + "notice": "Override of OwnableUpgradeable.transferOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there." + }, + "unstake(uint256,uint256)": { + "notice": "Withdraw staked tokens after stakeDuration has passed." + }, + "userStakingInfo(address,uint256)": { + "notice": "User stakingInfo map, user address => array of the staking info" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 609, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 612, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 591, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 906, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 2869, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 928, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_paused", + "offset": 0, + "slot": "151", + "type": "t_bool" + }, + { + "astId": 1033, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 116, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_owner", + "offset": 0, + "slot": "201", + "type": "t_address" + }, + { + "astId": 236, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 8981, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_globalOwner", + "offset": 0, + "slot": "251", + "type": "t_contract(GlobalOwner)5028" + }, + { + "astId": 9065, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 9083, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_globalPause", + "offset": 0, + "slot": "302", + "type": "t_contract(GlobalPause)5104" + }, + { + "astId": 9142, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "303", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 9156, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_globalBlacklist", + "offset": 0, + "slot": "353", + "type": "t_contract(GlobalBlacklist)4981" + }, + { + "astId": 9230, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "354", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 10249, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "404", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 10340, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "454", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 1048, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "_status", + "offset": 0, + "slot": "504", + "type": "t_uint256" + }, + { + "astId": 1117, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "__gap", + "offset": 0, + "slot": "505", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 5178, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "stakeRewardToken", + "offset": 0, + "slot": "554", + "type": "t_contract(IERC20Upgradeable)1808" + }, + { + "astId": 5181, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "stakeDurationForPerks", + "offset": 0, + "slot": "555", + "type": "t_uint256" + }, + { + "astId": 5184, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "stakeAmountForPerks", + "offset": 0, + "slot": "556", + "type": "t_uint256" + }, + { + "astId": 5189, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "stakeDurationInfos", + "offset": 0, + "slot": "557", + "type": "t_array(t_struct(StakeDurationInfo)5170_storage)dyn_storage" + }, + { + "astId": 5192, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "rewardsDuration", + "offset": 0, + "slot": "558", + "type": "t_uint256" + }, + { + "astId": 5195, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "finishAt", + "offset": 0, + "slot": "559", + "type": "t_uint256" + }, + { + "astId": 5198, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "lastUpdateTime", + "offset": 0, + "slot": "560", + "type": "t_uint256" + }, + { + "astId": 5201, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "rewardRatePerSec", + "offset": 0, + "slot": "561", + "type": "t_uint256" + }, + { + "astId": 5204, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "rewardPerTokenStored", + "offset": 0, + "slot": "562", + "type": "t_uint256" + }, + { + "astId": 5207, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "totalStaked", + "offset": 0, + "slot": "563", + "type": "t_uint256" + }, + { + "astId": 5209, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "totalWeightedStake", + "offset": 0, + "slot": "564", + "type": "t_uint256" + }, + { + "astId": 5216, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "userStakingInfo", + "offset": 0, + "slot": "565", + "type": "t_mapping(t_address,t_array(t_struct(StakingInfo)5165_storage)dyn_storage)" + }, + { + "astId": 5219, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "totalRewards", + "offset": 0, + "slot": "566", + "type": "t_uint256" + }, + { + "astId": 5258, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "highTierAccounts", + "offset": 0, + "slot": "567", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(StakeDurationInfo)5170_storage)dyn_storage": { + "base": "t_struct(StakeDurationInfo)5170_storage", + "encoding": "dynamic_array", + "label": "struct LDYStaking.StakeDurationInfo[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(StakingInfo)5165_storage)dyn_storage": { + "base": "t_struct(StakingInfo)5165_storage", + "encoding": "dynamic_array", + "label": "struct LDYStaking.StakingInfo[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(GlobalBlacklist)4981": { + "encoding": "inplace", + "label": "contract GlobalBlacklist", + "numberOfBytes": "20" + }, + "t_contract(GlobalOwner)5028": { + "encoding": "inplace", + "label": "contract GlobalOwner", + "numberOfBytes": "20" + }, + "t_contract(GlobalPause)5104": { + "encoding": "inplace", + "label": "contract GlobalPause", + "numberOfBytes": "20" + }, + "t_contract(IERC20Upgradeable)1808": { + "encoding": "inplace", + "label": "contract IERC20Upgradeable", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_array(t_struct(StakingInfo)5165_storage)dyn_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct LDYStaking.StakingInfo[])", + "numberOfBytes": "32", + "value": "t_array(t_struct(StakingInfo)5165_storage)dyn_storage" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_struct(StakeDurationInfo)5170_storage": { + "encoding": "inplace", + "label": "struct LDYStaking.StakeDurationInfo", + "members": [ + { + "astId": 5167, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "duration", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 5169, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "multiplier", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_struct(StakingInfo)5165_storage": { + "encoding": "inplace", + "label": "struct LDYStaking.StakingInfo", + "members": [ + { + "astId": 5156, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "stakedAmount", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 5158, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "unStakeAt", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 5160, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "duration", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 5162, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "rewardPerTokenPaid", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 5164, + "contract": "contracts/src/LDYStaking.sol:LDYStaking", + "label": "rewards", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "numberOfBytes": "160" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/contracts/hardhat/deployments/arbitrum/LDYStaking_Proxy.json b/contracts/hardhat/deployments/arbitrum/LDYStaking_Proxy.json new file mode 100644 index 00000000..3d1ad933 --- /dev/null +++ b/contracts/hardhat/deployments/arbitrum/LDYStaking_Proxy.json @@ -0,0 +1,144 @@ +{ + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", + "receipt": { + "to": null, + "from": "0x0F97f63dA69A5b86Fe47517459D982198Cba22D2", + "contractAddress": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "transactionIndex": 9, + "gasUsed": "2191924", + "logsBloom": "0x00000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000200000000000000000000020000000000000000000040100000000000000000000100000000000000020000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcbd958b21081734c47ba6011a31430494cd445e45e914f0a4884c5be24e65f91", + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", + "logs": [ + { + "transactionIndex": 9, + "blockNumber": 218746026, + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000067efae630f0f7fae539b0f1eb1fc1c4cc4dc3e47" + ], + "data": "0x", + "logIndex": 14, + "blockHash": "0xcbd958b21081734c47ba6011a31430494cd445e45e914f0a4884c5be24e65f91" + }, + { + "transactionIndex": 9, + "blockNumber": 218746026, + "transactionHash": "0x57e684ac50fc968b25d8ef4274e9cc7b967bfa52b847cb26fdaf174007384707", + "address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 15, + "blockHash": "0xcbd958b21081734c47ba6011a31430494cd445e45e914f0a4884c5be24e65f91" + } + ], + "blockNumber": 218746026, + "cumulativeGasUsed": "5043212", + "status": 1, + "byzantium": true + }, + "args": [ + "0x67efAe630f0F7faE539B0F1EB1fC1C4cc4dc3e47", + "0x63d07120000000000000000000000000e4af4573bfc5f04d8b84c61744de8a94059f2462000000000000000000000000d4d4c68ce70fa88b9e527dd3a4a6d19c5cbdd4db000000000000000000000000ca55a2394876e7cf52e99ab36fc9151a7d9cf350000000000000000000000000999faf0af2ff109938eefe6a7bf91ca56f0d07e100000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000001ea6e0000000000000000000000000000000000000000000000003635c9adc5dea00000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000028de800000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000f53700000000000000000000000000000000000000000000000000000000000000ea600000000000000000000000000000000000000000000000000000000001ea6e0000000000000000000000000000000000000000000000000000000000000186a0" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":\"ERC1967Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161084e38038061084e83398101604081905261002291610349565b61004d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610417565b600080516020610807833981519152146100695761006961043c565b6100758282600061007c565b50506104a1565b610085836100b2565b6000825111806100925750805b156100ad576100ab83836100f260201b6100291760201c565b505b505050565b6100bb8161011e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606101178383604051806060016040528060278152602001610827602791396101de565b9392505050565b610131816102bc60201b6100551760201c565b6101985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101bd60008051602061080783398151915260001b6102cb60201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161018f565b600080856001600160a01b0316856040516102619190610452565b600060405180830381855af49150503d806000811461029c576040519150601f19603f3d011682016040523d82523d6000602084013e6102a1565b606091505b5090925090506102b28282866102ce565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102dd575081610117565b8251156102ed5782518084602001fd5b8160405162461bcd60e51b815260040161018f919061046e565b634e487b7160e01b600052604160045260246000fd5b60005b83811015610338578181015183820152602001610320565b838111156100ab5750506000910152565b6000806040838503121561035c57600080fd5b82516001600160a01b038116811461037357600080fd5b60208401519092506001600160401b038082111561039057600080fd5b818501915085601f8301126103a457600080fd5b8151818111156103b6576103b6610307565b604051601f8201601f19908116603f011681019083821181831017156103de576103de610307565b816040528281528860208487010111156103f757600080fd5b61040883602083016020880161031d565b80955050505050509250929050565b60008282101561043757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825161046481846020870161031d565b9190910192915050565b602081526000825180602084015261048d81604085016020870161031d565b601f01601f19169190910160400192915050565b610357806104b06000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033", + "devdoc": { + "details": "This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/contracts/hardhat/deployments/arbitrum/LUSDC.json b/contracts/hardhat/deployments/arbitrum/LUSDC.json index 99418be5..836c287a 100644 --- a/contracts/hardhat/deployments/arbitrum/LUSDC.json +++ b/contracts/hardhat/deployments/arbitrum/LUSDC.json @@ -105,6 +105,12 @@ "internalType": "enum LToken.Status", "name": "newStatus", "type": "uint8" + }, + { + "indexed": false, + "internalType": "int256", + "name": "newId", + "type": "int256" } ], "name": "ActivityEvent", @@ -966,6 +972,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrwalFeeInEth_", + "type": "uint256" + } + ], + "name": "setWithdrwalFeeInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1302,6 +1321,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "withdrwalFeeInEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1365,22 +1397,12 @@ "0xA3B0dbA08B0e83Aa6DBcf2fB11eAFb209C84A21F", "0x1459457a000000000000000000000000e4af4573bfc5f04d8b84c61744de8a94059f2462000000000000000000000000d4d4c68ce70fa88b9e527dd3a4a6d19c5cbdd4db000000000000000000000000ca55a2394876e7cf52e99ab36fc9151a7d9cf35000000000000000000000000006f54b7f27eec56616b951598baa3b84d7660ab4000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831" ], - "numDeployments": 1, + "numDeployments": 4, "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":\"ERC1967Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405260405161084e38038061084e83398101604081905261002291610349565b61004d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610417565b600080516020610807833981519152146100695761006961043c565b6100758282600061007c565b50506104a1565b610085836100b2565b6000825111806100925750805b156100ad576100ab83836100f260201b6100291760201c565b505b505050565b6100bb8161011e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606101178383604051806060016040528060278152602001610827602791396101de565b9392505050565b610131816102bc60201b6100551760201c565b6101985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101bd60008051602061080783398151915260001b6102cb60201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161018f565b600080856001600160a01b0316856040516102619190610452565b600060405180830381855af49150503d806000811461029c576040519150601f19603f3d011682016040523d82523d6000602084013e6102a1565b606091505b5090925090506102b28282866102ce565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102dd575081610117565b8251156102ed5782518084602001fd5b8160405162461bcd60e51b815260040161018f919061046e565b634e487b7160e01b600052604160045260246000fd5b60005b83811015610338578181015183820152602001610320565b838111156100ab5750506000910152565b6000806040838503121561035c57600080fd5b82516001600160a01b038116811461037357600080fd5b60208401519092506001600160401b038082111561039057600080fd5b818501915085601f8301126103a457600080fd5b8151818111156103b6576103b6610307565b604051601f8201601f19908116603f011681019083821181831017156103de576103de610307565b816040528281528860208487010111156103f757600080fd5b61040883602083016020880161031d565b80955050505050509250929050565b60008282101561043757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825161046481846020870161031d565b9190910192915050565b602081526000825180602084015261048d81604085016020870161031d565b601f01601f19169190910160400192915050565b610357806104b06000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033", - "execute": { - "methodName": "initialize", - "args": [ - "0xe4Af4573bFc5F04D8b84c61744de8A94059f2462", - "0xd4D4c68CE70fa88B9E527DD3A4a6d19c5cbdd4dB", - "0xcA55A2394876e7Cf52e99Ab36Fc9151a7d9CF350", - "0x06f54B7f27eEC56616b951598BaA3B84D7660AB4", - "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" - ] - }, - "implementation": "0xA3B0dbA08B0e83Aa6DBcf2fB11eAFb209C84A21F", + "implementation": "0x8584BCd220A048104e654F842C56E33d37d6aEe3", "devdoc": { "details": "This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.", "kind": "dev", diff --git a/contracts/hardhat/deployments/arbitrum/LUSDC_Implementation.json b/contracts/hardhat/deployments/arbitrum/LUSDC_Implementation.json index 208cbea5..04d186f9 100644 --- a/contracts/hardhat/deployments/arbitrum/LUSDC_Implementation.json +++ b/contracts/hardhat/deployments/arbitrum/LUSDC_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0xa2B6487Cc828Ba9260013Ec671F29a4a7778a64B", + "address": "0x8584BCd220A048104e654F842C56E33d37d6aEe3", "abi": [ { "anonymous": false, @@ -964,6 +964,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrwalFeeInEth_", + "type": "uint256" + } + ], + "name": "setWithdrwalFeeInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1299,43 +1312,56 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "withdrwalFeeInEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ], - "transactionHash": "0xd2f126d17ef6d8a0a6eabe6d554a0027d61feec0bcd4f88be48c0b140b7b0e8b", + "transactionHash": "0xb472653287ffaab1101469a77e3ded8063c52d61e7772c53c79d7e726bc15643", "receipt": { "to": null, - "from": "0x9644fFCE92Ff305f14AF9aCD71c7ccbBE6478023", - "contractAddress": "0xa2B6487Cc828Ba9260013Ec671F29a4a7778a64B", - "transactionIndex": 7, - "gasUsed": "38550228", - "logsBloom": "0x00000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd514f72afa89bc71a508f6e6fd291f1ade50864a739c2e66981430b4cb53d8a6", - "transactionHash": "0xd2f126d17ef6d8a0a6eabe6d554a0027d61feec0bcd4f88be48c0b140b7b0e8b", + "from": "0x0F97f63dA69A5b86Fe47517459D982198Cba22D2", + "contractAddress": "0x8584BCd220A048104e654F842C56E33d37d6aEe3", + "transactionIndex": 6, + "gasUsed": "12292908", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000002000000000000000000000000000000002000000000000000000440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa1900f9527168d2bb00863f19bfadb2d6fa88b51dc015cabce4920b1604b10fb", + "transactionHash": "0xb472653287ffaab1101469a77e3ded8063c52d61e7772c53c79d7e726bc15643", "logs": [ { - "transactionIndex": 7, - "blockNumber": 165375420, - "transactionHash": "0xd2f126d17ef6d8a0a6eabe6d554a0027d61feec0bcd4f88be48c0b140b7b0e8b", - "address": "0xa2B6487Cc828Ba9260013Ec671F29a4a7778a64B", + "transactionIndex": 6, + "blockNumber": 218984540, + "transactionHash": "0xb472653287ffaab1101469a77e3ded8063c52d61e7772c53c79d7e726bc15643", + "address": "0x8584BCd220A048104e654F842C56E33d37d6aEe3", "topics": [ "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" ], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 28, - "blockHash": "0xd514f72afa89bc71a508f6e6fd291f1ade50864a739c2e66981430b4cb53d8a6" + "logIndex": 13, + "blockHash": "0xa1900f9527168d2bb00863f19bfadb2d6fa88b51dc015cabce4920b1604b10fb" } ], - "blockNumber": 165375420, - "cumulativeGasUsed": "44269912", + "blockNumber": 218984540, + "cumulativeGasUsed": "13812969", "status": 1, "byzantium": true }, "args": [], "numDeployments": 2, - "solcInputHash": "d74114448a35b14f4563775ab35bca2b", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newAPRUD7x3\",\"type\":\"uint16\"}],\"name\":\"APRChangeEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int256\",\"name\":\"id\",\"type\":\"int256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum LToken.Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountAfterFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum LToken.Status\",\"name\":\"newStatus\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"newId\",\"type\":\"int256\"}],\"name\":\"ActivityEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balanceBefore\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewards\",\"type\":\"uint256\"}],\"name\":\"MintedRewardsEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTVL\",\"type\":\"uint256\"}],\"name\":\"TVLChangeEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"cancelWithdrawalRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositFor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feesRateUD7x3\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"frozenRequests\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fund\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAPR\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpectedRetained\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"getWithdrawnAmountAndFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawnAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalBlacklist\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalPause\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"globalOwner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"globalPause_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"globalBlacklist_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ldyStaking_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingToken\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"instantWithdrawal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"invested\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ldyStaking\",\"outputs\":[{\"internalType\":\"contract LDYStaking\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"listenerContract\",\"type\":\"address\"}],\"name\":\"listenToTransfers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"processBigQueuedRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"processQueuedRequests\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"realBalanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"realTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"recoverERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"recoverUnderlying\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repatriate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"requestWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"retentionRateUD7x3\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardsRedirectsFromTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rewardsRedirectsToFrom\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"aprUD7x3\",\"type\":\"uint16\"}],\"name\":\"setAPR\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"feesRateUD7x3_\",\"type\":\"uint32\"}],\"name\":\"setFeesRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"fund_\",\"type\":\"address\"}],\"name\":\"setFund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"ldyStakingAddress\",\"type\":\"address\"}],\"name\":\"setLDYStaking\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"retentionRateUD7x3_\",\"type\":\"uint32\"}],\"name\":\"setRetentionRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawer_\",\"type\":\"address\"}],\"name\":\"setWithdrawer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"startRewardsRedirection\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"stopRewardsRedirection\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalQueued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfersListeners\",\"outputs\":[{\"internalType\":\"contract ITransfersListener\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unclaimedFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"underlying\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"listenerContract\",\"type\":\"address\"}],\"name\":\"unlistenToTransfers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"unmintedRewardsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usableUnderlyings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdrawalQueue\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawalQueueCursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawer\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Lila Rest (https://lila.rest)\",\"custom:oz-upgrades-unsafe-allow\":\"external-library-linking\",\"custom:security-contact\":\"security@ledgity.comsecurity@ledgity.com\",\"details\":\"Definitions: - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio). - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees). - Instant: Processed immediately. - Requested: Queued for later processing. - Big Requested: A requested withdrawal exceeding half of the retention rate. - (Withdrawal) queue: An list of all requested withdrawals sorted by priority. - Request ID: The index of a withdrawal request in the queue array. - Retention rate: Maximum fraction of underlying tokens TVL that the contract can retain. - Fees Rate: Percentage of fees applied to successful withdrawals. - Usable underlyings: Amount of underlying tokens that have been deposited through expected ways and are so considered as safe to use by the contract. - Transfers listeners: External contracts listening on L-Tokens transfers. - Fund wallet: Wallet managed by the Ledgity's financial team. - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request processing. Note that words between parenthesis are sometimes omitted for brevity.Security: This contract can safely receive funds immediately after initialization. (i.e., there is no way for funds to be sent to non-owned addresses). It is however recommended to replace ASAP owner and fund wallets by multi-sig wallets.For further details, see \\\"LToken\\\" section of whitepaper.\",\"events\":{\"APRChangeEvent(uint16)\":{\"params\":{\"newAPRUD7x3\":\"The new APR in UD7x3 format.\"}},\"ActivityEvent(int256,address,uint8,uint256,uint256,uint8,int256)\":{\"params\":{\"account\":\"The account involved in the activity.\",\"action\":\"The type of activity.\",\"amount\":\"The amount of underlying tokens involved in the activity.\",\"id\":\"ID of the involved withdrawal request or NO_ID (-1) if not applicable.\",\"newId\":\"The new ID of the request if it has been moved in the queue.\",\"newStatus\":\"The new status of the activity.\"}},\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is changed.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"MintedRewardsEvent(address,uint256,uint256)\":{\"params\":{\"account\":\"The account that received the rewards.\",\"balanceBefore\":\"The balance of the account before the minting.\",\"rewards\":\"The amount of minted rewards.\"}},\"Paused(address)\":{\"details\":\"Emitted when the pause is triggered by `account`.\"},\"TVLChangeEvent(uint256)\":{\"details\":\"TVL = realTotalSupply()\",\"params\":{\"newTVL\":\"The new TVL of the contract.\"}},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"},\"Unpaused(address)\":{\"details\":\"Emitted when the pause is lifted by `account`.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have not been yet minted to the specified account.\",\"params\":{\"account\":\"The account to check the total balance of.\"},\"returns\":{\"_0\":\"The total balance of the account.\"}},\"cancelWithdrawalRequest(uint256)\":{\"params\":{\"requestId\":\"The ID of the withdrawal request to cancel.\"}},\"decimals()\":{\"details\":\"The ERC20WrapperUpgradeable version is preferred because it mirrors the decimals amount of the underlying stablecoin token.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"deposit(uint256)\":{\"params\":{\"amount\":\"The amount of underlying tokens to deposit.\"}},\"depositFor(address,uint256)\":{\"details\":\"Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\"},\"getAPR()\":{\"returns\":{\"_0\":\"The current APR in UD7x3 format.\"}},\"getExpectedRetained()\":{\"returns\":{\"amount\":\"The expected amount of retained underlying tokens.\"}},\"getWithdrawnAmountAndFees(address,uint256)\":{\"params\":{\"account\":\"The account initiating the withdrawal.\",\"amount\":\"The amount of the withdrawal.\"}},\"globalBlacklist()\":{\"returns\":{\"_0\":\"The address of the GlobalBlacklist contract.\"}},\"globalOwner()\":{\"returns\":{\"_0\":\"The address of the GlobalOwner contract.\"}},\"globalPause()\":{\"returns\":{\"_0\":\"The address of the GlobalPause contract.\"}},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"initialize(address,address,address,address,address)\":{\"details\":\"See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\",\"params\":{\"globalBlacklist_\":\"The address of the GlobalBlacklist contract.\",\"globalOwner_\":\"The address of the GlobalOwner contract.\",\"globalPause_\":\"The address of the GlobalPause contract.\",\"underlyingToken\":\"The address of the underlying stablecoin ERC20 token.\"}},\"instantWithdrawal(uint256)\":{\"details\":\"In order to save some gas and time to users, frontends should propose this function to users only when it has been verified that it will not revert. They should propose the requestWithdrawal() function otherwise.\",\"params\":{\"amount\":\"The amount L-Tokens to withdraw.\"}},\"invested()\":{\"returns\":{\"_0\":\"The reference to the invested token contract.\"}},\"listenToTransfers(address)\":{\"details\":\"Each time a transfer occurs, the onLTokenTransfer() function of the specified contract will be called.IMPORTANT SECURITY NOTE: This method is not intended to be used with contracts that are not owned by the Ledgity team.\",\"params\":{\"listenerContract\":\"The address of the new transfers listener contract.\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"owner()\":{\"returns\":{\"_0\":\"The address of the owner\"}},\"paused()\":{\"details\":\"Both version are the same as ERC20BaseUpgradeable.paused() mirrors GlobalPausableUpgradeable.paused(), so a random one is chosen.\",\"returns\":{\"_0\":\"Whether the contract is paused or not.\"}},\"processBigQueuedRequest(uint256)\":{\"details\":\"In contrast to non-big requests processing, this function will uses to fund wallet's balance to fill the request. This allows processing requests that are greater than retention rate without having to exceed this rate on the contract.\",\"params\":{\"requestId\":\"The ID of the big request to process.\"}},\"processQueuedRequests()\":{\"details\":\"For further details, see \\\"LToken > Withdrawals\\\" section of whitepaper.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"realBalanceOf(address)\":{\"params\":{\"account\":\"The account to check the real balance of.\"},\"returns\":{\"_0\":\"The real balance of the account.\"}},\"realTotalSupply()\":{\"returns\":{\"_0\":\"The real total supply of L-Tokens.\"}},\"recoverERC20(address,uint256)\":{\"details\":\"This override of RecoverableUpgradeable.recoverERC20() prevents the recovered token from being the underlying token.\",\"params\":{\"amount\":\"The amount of token to recover.\",\"tokenAddress\":\"The address of the token to recover.\"}},\"recoverUnderlying()\":{\"details\":\"To prevent owner from being able to drain the contract, this function only allows recovering \\\"unusable\\\" underlying tokens, i.e., tokens that have not been sent through fund() or deposit() functions.\"},\"repatriate(uint256)\":{\"details\":\"The function will revert if repatriated amount makes the contract exceeding the retention rate.\",\"params\":{\"amount\":\"The amount of underlying tokens to repatriate.\"}},\"requestWithdrawal(uint256)\":{\"details\":\"The sender must attach 0.003 ETH to pre-pay the future processing gas fees paid by the withdrawer wallet.\",\"params\":{\"amount\":\"The amount L-Tokens to withdraw.\"}},\"setAPR(uint16)\":{\"params\":{\"aprUD7x3\":\"The new APR in UD7x3 format.\"}},\"setFeesRate(uint32)\":{\"params\":{\"feesRateUD7x3_\":\"The new withdrawal fee rate in UD7x3 format.\"}},\"setFund(address)\":{\"params\":{\"fund_\":\"The address of the new fund wallet.\"}},\"setLDYStaking(address)\":{\"params\":{\"ldyStakingAddress\":\"The address of the new LDYStaking contract.\"}},\"setRetentionRate(uint32)\":{\"details\":\"The retention rate is capped at 10%, which ensures that no more than 10% of deposited assets will ever be exposed in this contract (reduces attack surface).\",\"params\":{\"retentionRateUD7x3_\":\"The new retention rate in UD7x3 format.\"}},\"setWithdrawer(address)\":{\"params\":{\"withdrawer_\":\"The address of the new withdrawer wallet.\"}},\"startRewardsRedirection(address,address)\":{\"params\":{\"from\":\"The address of the account to redirect rewards from.\",\"to\":\"The address of the account to redirect rewards to.\"}},\"stopRewardsRedirection(address,address)\":{\"params\":{\"from\":\"The address of the account to stop redirecting rewards from.\",\"to\":\"The address of the account to stop redirecting rewards to.\"}},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"returns\":{\"_0\":\"The total supply of L-Tokens.\"}},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"},\"underlying()\":{\"details\":\"Returns the address of the underlying ERC-20 token that is being wrapped.\"},\"unlistenToTransfers(address)\":{\"details\":\"The onLTokenTransfer() function of the specified contract will not be called anymore each time a L-Token transfer occurs.\",\"params\":{\"listenerContract\":\"The address of the listener contract.\"}},\"unmintedRewardsOf(address)\":{\"details\":\"This is a public implementation of InvestUpgradeable_rewardsOf(). In the context of LToken, this function returns the amount of rewards that have not been distributed/minted yet to the specified account.This is particularly useful for off-chain services to display charts and statistics, as seen in the Ledgity Yield's frontend.\",\"params\":{\"account\":\"The account to check the unminted rewards of.\"},\"returns\":{\"_0\":\"The amount of account's unminted rewards.\"}},\"upgradeTo(address)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"withdrawTo(address,uint256)\":{\"details\":\"Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\"}},\"stateVariables\":{\"frozenRequests\":{\"details\":\"If a request emitter as been blacklisted, its request is moved here to prevent it from blocking the queue.\"},\"transfersListeners\":{\"details\":\"onLTokenTransfer() functions of those contracts will be called on each transfer.\"},\"usableUnderlyings\":{\"details\":\"Are usable, only underlying tokens deposit through deposit() or fund() functions.\"}},\"title\":\"LToken\",\"version\":1},\"userdoc\":{\"events\":{\"APRChangeEvent(uint16)\":{\"notice\":\"Emitted to inform listeners about a change in the APR's value.\"},\"ActivityEvent(int256,address,uint8,uint256,uint256,uint8,int256)\":{\"notice\":\"Emitted to inform listerners about an activity related to deposits and withdrawals.\"},\"MintedRewardsEvent(address,uint256,uint256)\":{\"notice\":\"Emitted to inform listeners that some rewards have been minted.\"},\"TVLChangeEvent(uint256)\":{\"notice\":\"Emitted to inform listeners about a change in the contract's TVL.\"}},\"kind\":\"user\",\"methods\":{\"balanceOf(address)\":{\"notice\":\"Retrieves the total balance of L-Tokens that belong to the account.\"},\"cancelWithdrawalRequest(uint256)\":{\"notice\":\"Cancels a given withdrawal request. The request emitter receive back its L-Tokens and no fees will be charged.\"},\"claimFees()\":{\"notice\":\"Used by owner to claim fees generated from successful withdrawals.\"},\"decimals()\":{\"notice\":\"Required override of decimals() which is implemented by both ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\"},\"deposit(uint256)\":{\"notice\":\"Allows exchanging some underlying tokens for the same amount of L-Tokens.\"},\"depositFor(address,uint256)\":{\"notice\":\"Override of ERC20WrapperUpgradeable.depositFor() that reverts. Use deposit() function instead.\"},\"feesRateUD7x3()\":{\"notice\":\"Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\"},\"frozenRequests(uint256)\":{\"notice\":\"Holds a list of all currently frozen withdrawal requests.\"},\"fund()\":{\"notice\":\"Holds address of fund wallet (managed by Ledgity financial team).\"},\"getAPR()\":{\"notice\":\"Retrieves the most recently set APR.\"},\"getExpectedRetained()\":{\"notice\":\"Computes the maximum amount of underlying tokens that should be retained by the contract (based on retention rate).\"},\"getWithdrawnAmountAndFees(address,uint256)\":{\"notice\":\"Computes fees and net withdrawn amount for a given account withdrawing a given amount.\"},\"globalBlacklist()\":{\"notice\":\"Retrieves the address of GlobalBlacklist contract.\"},\"globalOwner()\":{\"notice\":\"Retrieves the address of GlobalOwner contract.\"},\"globalPause()\":{\"notice\":\"Retrieves the address of GlobalPause contract.\"},\"initialize(address,address,address,address,address)\":{\"notice\":\"Initializer function of the contract. It replaces the constructor() function in the context of upgradeable contracts.\"},\"instantWithdrawal(uint256)\":{\"notice\":\"Allows instaneously exchanging a given amount of L-Tokens for the same amount of underlying tokens. It will fail if the contract currently doesn't hold enough underlying tokens to cover the withdrawal.\"},\"invested()\":{\"notice\":\"Retrieves the reference to the invested token contract.\"},\"ldyStaking()\":{\"notice\":\"Holds a reference to the LDYStaking contract.\"},\"listenToTransfers(address)\":{\"notice\":\"Adds a new contract to the L-Token transfers list.\"},\"owner()\":{\"notice\":\"Override of OwnableUpgradeable.owner() that retrieves the owner's address from the GlobalOwner contract instead.\"},\"paused()\":{\"notice\":\"Required override of paused() which is implemented by both GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\"},\"processBigQueuedRequest(uint256)\":{\"notice\":\"Processes a given queued big withdrawal request (one that exceeds half of the retention rate).\"},\"processQueuedRequests()\":{\"notice\":\"Processes queued withdrawal requests until there is else no more requests, else not enough underlying tokens to continue.\"},\"realBalanceOf(address)\":{\"notice\":\"Retrieves the \\\"real\\\" balance of an account, i.e., excluding its not yet minted/distributed rewards.\"},\"realTotalSupply()\":{\"notice\":\"Returns the \\\"real\\\" amount of existing L-Tokens, i.e., excluding not yet minted withdrawal fees and L-Tokens currently in the withdrawal queue.\"},\"recoverERC20(address,uint256)\":{\"notice\":\"Recovers a specified amount of a given token address.\"},\"recoverUnderlying()\":{\"notice\":\"Recovers underlying tokens accidentally sent to the contract.\"},\"renounceOwnership()\":{\"notice\":\"Override of OwnableUpgradeable.renounceOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there.\"},\"repatriate(uint256)\":{\"notice\":\"Used by the fund wallet to repatriate underlying tokens on the contract whenever those are required to fulfill some withdrawal requests.\"},\"requestWithdrawal(uint256)\":{\"notice\":\"Allows requesting the exchange of a given amount of L-Tokens for the same amount of underlying tokens. The request will be automatically processed later.\"},\"retentionRateUD7x3()\":{\"notice\":\"Holds the retention rate in UD7x3 format.\"},\"rewardsRedirectsFromTo(address)\":{\"notice\":\"Holds active rewards redirections in both from->to and to->from[] ways.\"},\"setAPR(uint16)\":{\"notice\":\"Updates the investment APR. Restricted to owner.\"},\"setFeesRate(uint32)\":{\"notice\":\"Updates the current withdrawal fee rate.\"},\"setFund(address)\":{\"notice\":\"Updates the address of the fund wallet.\"},\"setLDYStaking(address)\":{\"notice\":\"Updates the address of LDYStaking contract.\"},\"setRetentionRate(uint32)\":{\"notice\":\"Updates the current underlying token retention rate.\"},\"setWithdrawer(address)\":{\"notice\":\"Updates the address of the withdrawer wallet.\"},\"startRewardsRedirection(address,address)\":{\"notice\":\"Enables redirection of rewards from one account to another.\"},\"stopRewardsRedirection(address,address)\":{\"notice\":\"Disable an active rewards redirection.\"},\"totalQueued()\":{\"notice\":\"Holds the amount of L-Tokens currently in the withdrawal queue.\"},\"totalSupply()\":{\"notice\":\"Retrives the total supply of L-Tokens, including not yet minted withdrawal fees and L-Tokens currently in the withdrawal queue.\"},\"transferOwnership(address)\":{\"notice\":\"Override of OwnableUpgradeable.transferOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there.\"},\"transfersListeners(uint256)\":{\"notice\":\"Holds a list of contracts' references that are listening to L-Tokens transfers.\"},\"unclaimedFees()\":{\"notice\":\"Holds the amount of withdrawal fees not yet claimed by contract's owner.\"},\"unlistenToTransfers(address)\":{\"notice\":\"Removes a contract from the L-Token transfers list.\"},\"unmintedRewardsOf(address)\":{\"notice\":\"Retrieves the amount of given account's not yet minted rewards.\"},\"usableUnderlyings()\":{\"notice\":\"Holds the amount of underlying tokens considered as usable by the contract.\"},\"withdrawTo(address,uint256)\":{\"notice\":\"Override of ERC20WrapperUpgradeable.withdrawTo() that reverts. Use instantWithdrawal() or requestWithdrawal() functions instead.\"},\"withdrawalQueue(uint256)\":{\"notice\":\"Holds an ordered list of active withdrawal requests.\"},\"withdrawalQueueCursor()\":{\"notice\":\"Holds the index of the next withdrawal request to process in the queue.\"},\"withdrawer()\":{\"notice\":\"Holds address of withdrawer wallet (managed by withdrawal server).\"}},\"notice\":\"Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e, investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin. As soon as a wallet holds some L-Tokens, it starts receiving rewards in the form of additional L-Tokens, which are auto-compounded over time.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/src/LToken.sol\":\"LToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n *\\n * _Available since v4.8.3._\\n */\\ninterface IERC1967Upgradeable {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0x47d6e06872b12e72c79d1b5eb55842f860b5fb1207b2317c2358d2766b950a7b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822ProxiableUpgradeable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeaconUpgradeable.sol\\\";\\nimport \\\"../../interfaces/IERC1967Upgradeable.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822Upgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/StorageSlotUpgradeable.sol\\\";\\nimport \\\"../utils/Initializable.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\\n function __ERC1967Upgrade_init() internal onlyInitializing {\\n }\\n\\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\\n }\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(AddressUpgradeable.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(AddressUpgradeable.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\\n }\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x584ebdf9c1118a7c773f98788e3f3ede01982bdf8932aa06f5acc7d54876e161\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeaconUpgradeable {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../interfaces/draft-IERC1822Upgradeable.sol\\\";\\nimport \\\"../ERC1967/ERC1967UpgradeUpgradeable.sol\\\";\\nimport \\\"./Initializable.sol\\\";\\n\\n/**\\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\\n *\\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\\n * `UUPSUpgradeable` with a custom implementation of upgrades.\\n *\\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n require(address(this) != __self, \\\"Function must be called through delegatecall\\\");\\n require(_getImplementation() == __self, \\\"Function must be called through active proxy\\\");\\n _;\\n }\\n\\n /**\\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\\n * callable on the implementing contract but not through proxies.\\n */\\n modifier notDelegated() {\\n require(address(this) == __self, \\\"UUPSUpgradeable: must not be called through delegatecall\\\");\\n _;\\n }\\n\\n /**\\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\\n */\\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\\n return _IMPLEMENTATION_SLOT;\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeTo(address newImplementation) public virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\\n * encoded in `data`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {upgradeTo} and {upgradeToAndCall}.\\n *\\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\\n *\\n * ```solidity\\n * function _authorizeUpgrade(address) internal override onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xb607cb94c27e89750f5ae2ccebcb94e654e926f6125f4fd4c6262c89875118ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20Upgradeable.sol\\\";\\nimport \\\"./extensions/IERC20MetadataUpgradeable.sol\\\";\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\\n __ERC20_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\",\"keccak256\":\"0xd14a627157b9a411d2410713e5dd3a377e9064bd5c194a90748bbf27ea625784\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20Upgradeable.sol\\\";\\nimport \\\"../../../security/PausableUpgradeable.sol\\\";\\nimport \\\"../../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * IMPORTANT: This contract does not include public pause and unpause functions. In\\n * addition to inheriting this contract, you must define both functions, invoking the\\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\\n * make the contract unpausable.\\n */\\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\\n function __ERC20Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __ERC20Pausable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xf0bd7f71ffae5f0addd375e8511fbf2ad8ca0c9b2606c32d92bdda7d76a7a81c\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Wrapper.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20Upgradeable.sol\\\";\\nimport \\\"../utils/SafeERC20Upgradeable.sol\\\";\\nimport \\\"../../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Extension of the ERC20 token contract to support token wrapping.\\n *\\n * Users can deposit and withdraw \\\"underlying tokens\\\" and receive a matching number of \\\"wrapped tokens\\\". This is useful\\n * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the\\n * wrapping of an existing \\\"basic\\\" ERC20 into a governance token.\\n *\\n * _Available since v4.2._\\n *\\n * @custom:storage-size 51\\n */\\nabstract contract ERC20WrapperUpgradeable is Initializable, ERC20Upgradeable {\\n IERC20Upgradeable private _underlying;\\n\\n function __ERC20Wrapper_init(IERC20Upgradeable underlyingToken) internal onlyInitializing {\\n __ERC20Wrapper_init_unchained(underlyingToken);\\n }\\n\\n function __ERC20Wrapper_init_unchained(IERC20Upgradeable underlyingToken) internal onlyInitializing {\\n require(underlyingToken != this, \\\"ERC20Wrapper: cannot self wrap\\\");\\n _underlying = underlyingToken;\\n }\\n\\n /**\\n * @dev See {ERC20-decimals}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n try IERC20MetadataUpgradeable(address(_underlying)).decimals() returns (uint8 value) {\\n return value;\\n } catch {\\n return super.decimals();\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\\n */\\n function underlying() public view returns (IERC20Upgradeable) {\\n return _underlying;\\n }\\n\\n /**\\n * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\\n */\\n function depositFor(address account, uint256 amount) public virtual returns (bool) {\\n address sender = _msgSender();\\n require(sender != address(this), \\\"ERC20Wrapper: wrapper can't deposit\\\");\\n SafeERC20Upgradeable.safeTransferFrom(_underlying, sender, address(this), amount);\\n _mint(account, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\\n */\\n function withdrawTo(address account, uint256 amount) public virtual returns (bool) {\\n _burn(_msgSender(), amount);\\n SafeERC20Upgradeable.safeTransfer(_underlying, account, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal\\n * function that can be exposed with access control if desired.\\n */\\n function _recover(address account) internal virtual returns (uint256) {\\n uint256 value = _underlying.balanceOf(address(this)) - totalSupply();\\n _mint(account, value);\\n return value;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x14bb62a60fcbc911c33ac0e5456bf31ed50b502c30be46ee15bd3b698e91bd81\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x605434219ebbe4653f703640f06969faa5a1d78f0bfef878e5ddbb1ca369ceeb\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\\n * _Available since v4.9 for `string`, `bytes`._\\n */\\nlibrary StorageSlotUpgradeable {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07ac95acad040f1fb1f6120dd0aa5f702db69446e95f82613721879d30de0908\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable2Step.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./Ownable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2Step is Ownable {\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n}\\n\",\"keccak256\":\"0xde231558366826d7cb61725af8147965a61c53b77a352cc8c9af38fc5a92ac3c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/src/DummyLDYStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Ownable2Step} from \\\"@openzeppelin/contracts/access/Ownable2Step.sol\\\";\\n\\n/**\\n * @title LDYStaking\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Replacement to the LDYStaking contract until the $LDY token is available and\\n * the real LDYStaking can be deployed.\\n *\\n * @dev This contract only implements tierOf() function from LDYStaking as it's the only\\n * one the LToken contract relies on.\\n *\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract LDYStaking is Ownable2Step {\\n /**\\n * @notice Holds a mapping of addresses that default to the highest staking tier.\\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\\n */\\n mapping(address => bool) public highTierAccounts;\\n\\n /**\\n * @notice Update high tier status of a given account.\\n * @param account The account to update the high tier status of.\\n */\\n function setHighTierAccount(address account, bool status) public onlyOwner {\\n highTierAccounts[account] = status;\\n }\\n\\n /**\\n * @dev Dummy tierOf() function that always return that the given account is not\\n * ellgible to any LDY staking tier, except if the account is in the\\n * defaultToHighestTier mapping.\\n * @param account The account to check the tier of.\\n */\\n function tierOf(address account) public view returns (uint256 tier) {\\n if (highTierAccounts[account]) return 3;\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x8f21c11de734a54181725bc34349590b950117be72b6b67fb81f044364a77544\",\"license\":\"MIT\"},\"contracts/src/GlobalBlacklist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./abstracts/GlobalOwnableUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalBlacklist\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Maintains a global mapping of blacklisted accounts on-chain. All contracts\\n * within the Ledgity Yield codebase reference this mapping to prevent access by\\n * blacklisted accounts.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\\n * and getter functions to easily check against this global blacklist.\\n *\\n * @dev For further details, see \\\"GlobalBlacklist\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\\n /**\\n * @notice Mapping of accounts to their blacklist status.\\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\\n */\\n mapping(address => bool) private _list;\\n\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function initialize(address globalOwner_) public initializer {\\n __GlobalOwnable_init(globalOwner_);\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @notice Adds a given account to the blacklist.\\n * @param account The account's address to be blacklisted.\\n */\\n function blacklist(address account) external onlyOwner {\\n require(account != address(0), \\\"L20\\\");\\n _list[account] = true;\\n }\\n\\n /**\\n * @notice Removes a given account from the blacklist.\\n * @param account The account's address to be un-blacklisted.\\n */\\n function unBlacklist(address account) external onlyOwner {\\n _list[account] = false;\\n }\\n\\n /**\\n * @notice Checks whether a given account is blacklisted.\\n * @param account Address of the account to check.\\n * @return 'true' if the account is blacklisted, 'false' otherwise\\n */\\n function isBlacklisted(address account) external view returns (bool) {\\n // Gas optimization: Avoid accessing storage if account is the zero address\\n // (e.g, during a mint or a burn of tokens)\\n if (account == address(0)) return false;\\n\\n // Else, return current account's blacklist status\\n return _list[account];\\n }\\n}\\n\",\"keccak256\":\"0x8e4d4072f74f9d683bf0b54d76fa08201cf507eb791d217178a0ee9d6aaa3ddf\",\"license\":\"MIT\"},\"contracts/src/GlobalOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {Ownable2StepUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalOwner\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Maintains the address of a global owner account shared by all contracts of the\\n * Ledgity Yield's codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\\n * owner() function that retrieves the owner's address from this contract instead.\\n *\\n * @dev For further details, see \\\"GlobalOwner\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n */\\n function initialize() public initializer {\\n __Ownable2Step_init();\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0xe539a2010c0dfb59a9084d9ee1a7e1b92228b9e8557df50d477eee653657e987\",\"license\":\"MIT\"},\"contracts/src/GlobalPause.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./abstracts/GlobalOwnableUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalPause\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Maintains a global pause state shared by all contracts of the Ledgity Yield\\n * codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\\n * paused() function that retrieves the pause state from this contract instead.\\n *\\n * @dev For further details, see \\\"GlobalPause\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalPause is\\n Initializable,\\n UUPSUpgradeable,\\n GlobalOwnableUpgradeable,\\n PausableUpgradeable\\n{\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function initialize(address globalOwner_) public initializer {\\n __GlobalOwnable_init(globalOwner_);\\n __Pausable_init();\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\\n * but restricted to contract's owner.\\n */\\n function pause() public onlyOwner {\\n _pause();\\n }\\n\\n function unpause() public onlyOwner {\\n _unpause();\\n }\\n}\\n\",\"keccak256\":\"0x5933aec9779d2d84e00678bf489c8349d8be84fcf479f2a18eb8571a3b900ada\",\"license\":\"MIT\"},\"contracts/src/LToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\n// Contracts\\nimport {ERC20WrapperUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\\\";\\nimport \\\"./abstracts/base/ERC20BaseUpgradeable.sol\\\";\\nimport {InvestUpgradeable} from \\\"./abstracts/InvestUpgradeable.sol\\\";\\nimport {LDYStaking} from \\\"./DummyLDYStaking.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport {SUD} from \\\"./libs/SUD.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport {IERC20MetadataUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\nimport {ITransfersListener} from \\\"./interfaces/ITransfersListener.sol\\\";\\n\\n/**\\n * @title LToken\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e,\\n * investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin.\\n * As soon as a wallet holds some L-Tokens, it starts receiving rewards in\\n * the form of additional L-Tokens, which are auto-compounded over time.\\n *\\n * @dev Definitions:\\n * - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio).\\n * - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees).\\n * - Instant: Processed immediately.\\n * - Requested: Queued for later processing.\\n * - Big Requested: A requested withdrawal exceeding half of the retention rate.\\n * - (Withdrawal) queue: An list of all requested withdrawals sorted by priority.\\n * - Request ID: The index of a withdrawal request in the queue array.\\n * - Retention rate: Maximum fraction of underlying tokens TVL that the contract can retain.\\n * - Fees Rate: Percentage of fees applied to successful withdrawals.\\n * - Usable underlyings: Amount of underlying tokens that have been deposited through\\n * expected ways and are so considered as safe to use by the contract.\\n * - Transfers listeners: External contracts listening on L-Tokens transfers.\\n * - Fund wallet: Wallet managed by the Ledgity's financial team.\\n * - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request\\n * processing.\\n *\\n * Note that words between parenthesis are sometimes omitted for brevity.\\n *\\n * @dev Security: This contract can safely receive funds immediately after initialization.\\n * (i.e., there is no way for funds to be sent to non-owned addresses). It is however\\n * recommended to replace ASAP owner and fund wallets by multi-sig wallets.\\n *\\n * @dev For further details, see \\\"LToken\\\" section of whitepaper.\\n * @custom:oz-upgrades-unsafe-allow external-library-linking\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @dev Represents type of actions triggering ActivityEvent events.\\n enum Action {\\n Deposit,\\n Withdraw\\n }\\n\\n /// @dev Represents different status of actions triggering ActivityEvent events.\\n enum Status {\\n Queued,\\n Cancelled,\\n Success,\\n Moved\\n }\\n\\n /**\\n * @notice Represents a withdrawal request in the queue.\\n * @dev A request fits in a single storage slot (32 bytes).\\n * @param account The account that initiated the request.\\n * @param amount The amount of underlying tokens requested.\\n */\\n struct WithdrawalRequest {\\n address account; // 20 bytes\\n uint96 amount; // 12 bytes\\n }\\n\\n /// @notice Upper limit of retention rate.\\n uint32 private constant MAX_RETENTION_RATE_UD7x3 = 10 * 10 ** 3; // 10%\\n\\n /// @notice Used in activity events to represent the absence of request ID.\\n int256 private constant NO_ID = -1;\\n\\n /// @notice Holds a reference to the LDYStaking contract.\\n LDYStaking public ldyStaking;\\n\\n /// @notice Holds address of withdrawer wallet (managed by withdrawal server).\\n address payable public withdrawer;\\n\\n /// @notice Holds address of fund wallet (managed by Ledgity financial team).\\n address public fund;\\n\\n /// @notice Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\\n uint32 public feesRateUD7x3;\\n\\n /// @notice Holds the retention rate in UD7x3 format.\\n uint32 public retentionRateUD7x3;\\n\\n /// @notice Holds the amount of withdrawal fees not yet claimed by contract's owner.\\n uint256 public unclaimedFees;\\n\\n /// @notice Holds the amount of L-Tokens currently in the withdrawal queue.\\n uint256 public totalQueued;\\n\\n /**\\n * @notice Holds the amount of underlying tokens considered as usable by the contract.\\n * @dev Are usable, only underlying tokens deposit through deposit() or fund() functions.\\n */\\n uint256 public usableUnderlyings;\\n\\n /// @notice Holds an ordered list of active withdrawal requests.\\n WithdrawalRequest[] public withdrawalQueue;\\n\\n /// @notice Holds the index of the next withdrawal request to process in the queue.\\n uint256 public withdrawalQueueCursor;\\n\\n /**\\n * @notice Holds a list of all currently frozen withdrawal requests.\\n * @dev If a request emitter as been blacklisted, its request is moved here to prevent\\n * it from blocking the queue.\\n */\\n WithdrawalRequest[] public frozenRequests;\\n\\n /**\\n * @notice Holds a list of contracts' references that are listening to L-Tokens transfers.\\n * @dev onLTokenTransfer() functions of those contracts will be called on each transfer.\\n */\\n ITransfersListener[] public transfersListeners;\\n\\n /**\\n * @notice Emitted to inform listeners about a change in the contract's TVL.\\n * @dev TVL = realTotalSupply()\\n * @param newTVL The new TVL of the contract.\\n */\\n event TVLChangeEvent(uint256 newTVL);\\n\\n /**\\n * @notice Emitted to inform listerners about an activity related to deposits and withdrawals.\\n * @param id ID of the involved withdrawal request or NO_ID (-1) if not applicable.\\n * @param account The account involved in the activity.\\n * @param action The type of activity.\\n * @param amount The amount of underlying tokens involved in the activity.\\n * @param newStatus The new status of the activity.\\n * @param newId The new ID of the request if it has been moved in the queue.\\n */\\n event ActivityEvent(\\n int256 indexed id,\\n address indexed account,\\n Action indexed action,\\n uint256 amount,\\n uint256 amountAfterFees,\\n Status newStatus,\\n int256 newId\\n );\\n\\n /**\\n * @notice Emitted to inform listeners that some rewards have been minted.\\n * @param account The account that received the rewards.\\n * @param balanceBefore The balance of the account before the minting.\\n * @param rewards The amount of minted rewards.\\n */\\n event MintedRewardsEvent(address indexed account, uint256 balanceBefore, uint256 rewards);\\n\\n /// @notice Reverts if the function caller is not the withdrawer wallet.\\n modifier onlyWithdrawer() {\\n require(_msgSender() == withdrawer, \\\"L39\\\");\\n _;\\n }\\n\\n /// @notice Reverts if the function caller is not the fund wallet.\\n modifier onlyFund() {\\n require(_msgSender() == fund, \\\"L40\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param underlyingToken The address of the underlying stablecoin ERC20 token.\\n */\\n function initialize(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n address ldyStaking_,\\n address underlyingToken\\n ) public initializer {\\n // Initialize ERC20 base.\\n string memory underlyingSymbol = IERC20MetadataUpgradeable(underlyingToken).symbol();\\n __ERC20Base_init(\\n globalOwner_,\\n globalPause_,\\n globalBlacklist_,\\n string(abi.encodePacked(\\\"Ledgity \\\", underlyingSymbol)),\\n string(abi.encodePacked(\\\"L\\\", underlyingSymbol))\\n );\\n\\n // IMPORTANT: Below calls must not be restricted to owner at any point.\\n // This is because the GlobalOwner contract may not be a fresh one, and so\\n // the contract deployer may not be the owner anymore after ERC20Base init.\\n\\n // Initialize other parents contracts.\\n __ERC20Wrapper_init(IERC20Upgradeable(underlyingToken));\\n __Invest_init_unchained(address(this));\\n\\n // Set LDYStaking contract\\n ldyStaking = LDYStaking(ldyStaking_);\\n\\n // Set initial withdrawal fees rate to 0.3%\\n feesRateUD7x3 = 300;\\n\\n // Set initial retention rate to 10%\\n retentionRateUD7x3 = 10_000;\\n\\n // Default withdrawer and fund wallet to contract owner address. This prevents\\n // any loss of funds if a deposit/withdrawal is made before those are manually set.\\n withdrawer = payable(owner());\\n fund = payable(owner());\\n }\\n\\n /**\\n * @notice Required override of decimals() which is implemented by both\\n * ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\\n * @dev The ERC20WrapperUpgradeable version is preferred because it mirrors the\\n * decimals amount of the underlying stablecoin token.\\n * @inheritdoc ERC20WrapperUpgradeable\\n */\\n function decimals()\\n public\\n view\\n override(ERC20Upgradeable, ERC20WrapperUpgradeable)\\n returns (uint8)\\n {\\n return ERC20WrapperUpgradeable.decimals();\\n }\\n\\n /**\\n * @notice Required override of paused() which is implemented by both\\n * GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\\n * @dev Both version are the same as ERC20BaseUpgradeable.paused() mirrors\\n * GlobalPausableUpgradeable.paused(), so a random one is chosen.\\n * @inheritdoc GlobalPausableUpgradeable\\n */\\n function paused()\\n public\\n view\\n virtual\\n override(GlobalPausableUpgradeable, ERC20BaseUpgradeable)\\n returns (bool)\\n {\\n return GlobalPausableUpgradeable.paused();\\n }\\n\\n /**\\n * @notice Updates the current withdrawal fee rate.\\n * @param feesRateUD7x3_ The new withdrawal fee rate in UD7x3 format.\\n */\\n function setFeesRate(uint32 feesRateUD7x3_) public onlyOwner {\\n feesRateUD7x3 = feesRateUD7x3_;\\n }\\n\\n /**\\n * @notice Updates the current underlying token retention rate.\\n * @dev The retention rate is capped at 10%, which ensures that no more than 10% of\\n * deposited assets will ever be exposed in this contract (reduces attack surface).\\n * @param retentionRateUD7x3_ The new retention rate in UD7x3 format.\\n */\\n function setRetentionRate(uint32 retentionRateUD7x3_) public onlyOwner {\\n require(retentionRateUD7x3_ <= MAX_RETENTION_RATE_UD7x3, \\\"L41\\\");\\n retentionRateUD7x3 = retentionRateUD7x3_;\\n }\\n\\n /**\\n * @notice Updates the address of LDYStaking contract.\\n * @param ldyStakingAddress The address of the new LDYStaking contract.\\n */\\n function setLDYStaking(address ldyStakingAddress) public onlyOwner {\\n ldyStaking = LDYStaking(ldyStakingAddress);\\n }\\n\\n /**\\n * @notice Updates the address of the withdrawer wallet.\\n * @param withdrawer_ The address of the new withdrawer wallet.\\n */\\n function setWithdrawer(address payable withdrawer_) public onlyOwner {\\n // Ensure address is not the zero address (pre-processing fees would be lost else)\\n require(withdrawer_ != address(0), \\\"L63\\\");\\n\\n // Set new withdrawer wallet's address\\n withdrawer = withdrawer_;\\n }\\n\\n /**\\n * @notice Updates the address of the fund wallet.\\n * @param fund_ The address of the new fund wallet.\\n */\\n function setFund(address payable fund_) public onlyOwner {\\n // Ensure address is not the zero address (deposited tokens would be lost else)\\n require(fund_ != address(0), \\\"L64\\\");\\n\\n // Set new fund wallet's address\\n fund = fund_;\\n }\\n\\n /**\\n * @notice Adds a new contract to the L-Token transfers list.\\n * @dev Each time a transfer occurs, the onLTokenTransfer() function of the\\n * specified contract will be called.\\n * @dev IMPORTANT SECURITY NOTE: This method is not intended to be used with\\n * contracts that are not owned by the Ledgity team.\\n * @param listenerContract The address of the new transfers listener contract.\\n */\\n function listenToTransfers(address listenerContract) public onlyOwner {\\n transfersListeners.push(ITransfersListener(listenerContract));\\n }\\n\\n /**\\n * @notice Removes a contract from the L-Token transfers list.\\n * @dev The onLTokenTransfer() function of the specified contract will not be called\\n * anymore each time a L-Token transfer occurs.\\n * @param listenerContract The address of the listener contract.\\n */\\n function unlistenToTransfers(address listenerContract) public onlyOwner {\\n // Find index of listener contract in transferListeners array\\n int256 index = -1;\\n uint256 transfersListenersLength = transfersListeners.length;\\n for (uint256 i = 0; i < transfersListenersLength; i++) {\\n if (address(transfersListeners[i]) == listenerContract) {\\n index = int256(i);\\n break;\\n }\\n }\\n\\n // Revert if given contract wasn't listening to transfers\\n require(index > -1, \\\"L42\\\");\\n\\n // Else, remove transfers listener contract from listeners array\\n transfersListeners[uint256(index)] = transfersListeners[transfersListenersLength - 1];\\n transfersListeners.pop();\\n }\\n\\n /**\\n * @notice Retrieves the amount of given account's not yet minted rewards.\\n * @dev This is a public implementation of InvestUpgradeable_rewardsOf(). In the\\n * context of LToken, this function returns the amount of rewards that have not been\\n * distributed/minted yet to the specified account.\\n * @dev This is particularly useful for off-chain services to display charts and\\n * statistics, as seen in the Ledgity Yield's frontend.\\n * @param account The account to check the unminted rewards of.\\n * @return The amount of account's unminted rewards.\\n */\\n function unmintedRewardsOf(address account) public view returns (uint256) {\\n return _rewardsOf(account, true);\\n }\\n\\n /**\\n * @notice Retrieves the \\\"real\\\" balance of an account, i.e., excluding its not yet\\n * minted/distributed rewards.\\n * @param account The account to check the real balance of.\\n * @return The real balance of the account.\\n */\\n function realBalanceOf(address account) public view returns (uint256) {\\n return super.balanceOf(account);\\n }\\n\\n /**\\n * @notice Retrieves the total balance of L-Tokens that belong to the account.\\n * @dev This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have\\n * not been yet minted to the specified account.\\n * @param account The account to check the total balance of.\\n * @return The total balance of the account.\\n */\\n function balanceOf(address account) public view override returns (uint256) {\\n return realBalanceOf(account) + unmintedRewardsOf(account);\\n }\\n\\n /**\\n * @notice Returns the \\\"real\\\" amount of existing L-Tokens, i.e., excluding not yet\\n * minted withdrawal fees and L-Tokens currently in the withdrawal queue.\\n * @return The real total supply of L-Tokens.\\n */\\n function realTotalSupply() public view returns (uint256) {\\n return super.totalSupply();\\n }\\n\\n /**\\n * @notice Retrives the total supply of L-Tokens, including not yet minted withdrawal\\n * fees and L-Tokens currently in the withdrawal queue.\\n * @return The total supply of L-Tokens.\\n */\\n function totalSupply() public view override returns (uint256) {\\n return realTotalSupply() + totalQueued + unclaimedFees;\\n }\\n\\n /**\\n * @notice Recovers a specified amount of a given token address.\\n * @dev This override of RecoverableUpgradeable.recoverERC20() prevents the recovered\\n * token from being the underlying token.\\n * @inheritdoc RecoverableUpgradeable\\n */\\n function recoverERC20(address tokenAddress, uint256 amount) public override onlyOwner {\\n // Ensure the token is not the underlying token\\n require(tokenAddress != address(underlying()), \\\"L43\\\");\\n\\n // Proceed to recovery\\n super.recoverERC20(tokenAddress, amount);\\n }\\n\\n /**\\n * @notice Recovers underlying tokens accidentally sent to the contract.\\n * @dev To prevent owner from being able to drain the contract, this function only\\n * allows recovering \\\"unusable\\\" underlying tokens, i.e., tokens that have not been\\n * sent through fund() or deposit() functions.\\n */\\n function recoverUnderlying() external onlyOwner {\\n // Compute the recoverable amount by taking the difference between the contract's\\n // balance and the amount of usable underlying tokens\\n uint256 recoverableAmount = underlying().balanceOf(address(this)) - usableUnderlyings;\\n\\n // Revert if there is nothing to recover\\n require(recoverableAmount > 0, \\\"L44\\\");\\n\\n // Else, proceed to underlying tokens recovery\\n super.recoverERC20(address(underlying()), recoverableAmount);\\n }\\n\\n /**\\n * @notice Retrieves the amount of underlying tokens invested by the given account.\\n * @dev Implementing this function is required by the InvestUpgradeable contract. In\\n * LToken contract, the investment of an account is equal to its real balance.\\n * @inheritdoc InvestUpgradeable\\n */\\n function _investmentOf(address account) internal view override returns (uint256) {\\n return realBalanceOf(account);\\n }\\n\\n /**\\n * @notice Distributes a specified amount of rewards (in L-Tokens) to a given account.\\n * @dev Implementing this function is required by the InvestUpgradeable contract so\\n * it can distribute rewards to accounts before each period reset.\\n * @dev InvestUpgradeable contract already ensure that amount > 0.\\n * @inheritdoc InvestUpgradeable\\n */\\n function _distributeRewards(address account, uint256 amount) internal override returns (bool) {\\n // Inform listeners of the rewards minting\\n emit MintedRewardsEvent(account, realBalanceOf(account), amount);\\n\\n // Mint L-Tokens rewards to account\\n _mint(account, amount);\\n\\n // Return true indicating to InvestUpgradeable that the rewards have been distributed\\n return true;\\n }\\n\\n /**\\n * @notice Override of ERC20._beforeTokenTransfer() to integrate with InvestUpgradeable.\\n * @dev This overriden version ensure that _beforeInvestmentChange() hook is properly\\n * called each time an account's balance is going to change.\\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\\n * already included in ERC20BaseUpgradeable._beforeTokenTransfer().\\n * @inheritdoc ERC20BaseUpgradeable\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal override(ERC20Upgradeable, ERC20BaseUpgradeable) {\\n ERC20BaseUpgradeable._beforeTokenTransfer(from, to, amount);\\n\\n // Invoke _beforeInvestmentChange() hook for non-zero accounts\\n if (from != address(0)) _beforeInvestmentChange(from, true);\\n if (to != address(0)) _beforeInvestmentChange(to, true);\\n }\\n\\n /**\\n * @notice Override of ERC20._afterTokenTransfer() to notify all transfers listeners.\\n * @dev This overriden version will trigger onLTokenTransfer() functions of all\\n * transfers listeners.\\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\\n * already checked in _beforeTokenTransfer().\\n * @inheritdoc ERC20Upgradeable\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\\n super._afterTokenTransfer(from, to, amount);\\n\\n // If some L-Token have been burned/minted, inform listeners of a TVL change\\n if (from == address(0) || to == address(0)) emit TVLChangeEvent(totalSupply());\\n\\n // Trigger onLTokenTransfer() functions of all the transfers listeners\\n for (uint256 i = 0; i < transfersListeners.length; i++) {\\n transfersListeners[i].onLTokenTransfer(from, to, amount);\\n }\\n }\\n\\n /**\\n * @notice Computes the maximum amount of underlying tokens that should be retained\\n * by the contract (based on retention rate).\\n * @return amount The expected amount of retained underlying tokens.\\n */\\n function getExpectedRetained() public view returns (uint256 amount) {\\n // Cache invested token's decimals number\\n uint256 d = SUD.decimalsOf(address(invested()));\\n\\n // Convert totalSupply and retentionRate to SUD\\n uint256 totalSupplySUD = SUD.fromAmount(totalSupply(), d);\\n uint256 retentionRateSUD = SUD.fromRate(retentionRateUD7x3, d);\\n\\n // Compute and return expected retained amount\\n uint256 expectedRetainedSUD = (totalSupplySUD * retentionRateSUD) / SUD.fromInt(100, d);\\n return SUD.toAmount(expectedRetainedSUD, d);\\n }\\n\\n /// @notice Transfers underlying tokens exceeding the retention rate to the fund wallet.\\n function _transferExceedingToFund() internal {\\n // Retrieve the expected amount retained\\n uint256 expectedRetained = getExpectedRetained();\\n\\n // If usable underlyings are less than or equal to expected retained, return\\n if (usableUnderlyings <= expectedRetained) return;\\n\\n // Else, exceeding amount is equal to difference between those values\\n uint256 exceedingAmount = usableUnderlyings - expectedRetained;\\n\\n // Decrease usable underlyings amount accordingly\\n usableUnderlyings -= exceedingAmount;\\n\\n // Transfer the exceeding amount to the fund wallet\\n underlying().safeTransfer(fund, exceedingAmount);\\n }\\n\\n /**\\n * @notice Override of ERC20WrapperUpgradeable.withdrawTo() that reverts.\\n * Use instantWithdrawal() or requestWithdrawal() functions instead.\\n * @inheritdoc ERC20WrapperUpgradeable\\n */\\n function withdrawTo(address account, uint256 amount) public pure override returns (bool) {\\n account; // Silence unused variable compiler warning\\n amount;\\n revert(\\\"L45\\\");\\n }\\n\\n /**\\n * @notice Override of ERC20WrapperUpgradeable.depositFor() that reverts.\\n * Use deposit() function instead.\\n * @inheritdoc ERC20WrapperUpgradeable\\n */\\n function depositFor(address account, uint256 amount) public pure override returns (bool) {\\n account; // Silence unused variable compiler warning\\n amount;\\n revert(\\\"L46\\\");\\n }\\n\\n /**\\n * @notice Allows exchanging some underlying tokens for the same amount of L-Tokens.\\n * @param amount The amount of underlying tokens to deposit.\\n */\\n function deposit(uint256 amount) public whenNotPaused notBlacklisted(_msgSender()) {\\n // Ensure the account has enough underlying tokens to deposit\\n require(underlying().balanceOf(_msgSender()) >= amount, \\\"L47\\\");\\n\\n // Update usable underlyings balance accordingly\\n usableUnderlyings += amount;\\n\\n // Inform listeners of the deposit activity event\\n emit ActivityEvent(\\n NO_ID,\\n _msgSender(),\\n Action.Deposit,\\n amount,\\n amount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Receive underlying tokens and mint L-Tokens to the account in a 1:1 ratio\\n super.depositFor(_msgSender(), amount);\\n\\n // Transfer exceeding underlying tokens to the fund wallet\\n _transferExceedingToFund();\\n }\\n\\n /**\\n * @notice Computes fees and net withdrawn amount for a given account withdrawing a\\n * given amount.\\n * @param account The account initiating the withdrawal.\\n * @param amount The amount of the withdrawal.\\n */\\n function getWithdrawnAmountAndFees(\\n address account,\\n uint256 amount\\n ) public view returns (uint256 withdrawnAmount, uint256 fees) {\\n // If the account is eligible to staking tier 2, no fees are applied\\n if (ldyStaking.tierOf(account) >= 2) return (amount, 0);\\n\\n // Cache invested token's decimals number\\n uint256 d = SUD.decimalsOf(address(invested()));\\n\\n // Convert amount and fees rate to SUD\\n uint256 amountSUD = SUD.fromAmount(amount, d);\\n uint256 feesRateSUD = SUD.fromRate(feesRateUD7x3, d);\\n\\n // Compute fees and withdrawn amount (initial amount minus fees)\\n uint256 feesSUD = (amountSUD * feesRateSUD) / SUD.fromInt(100, d);\\n fees = SUD.toAmount(feesSUD, d);\\n withdrawnAmount = amount - fees;\\n }\\n\\n /**\\n * @notice Allows instaneously exchanging a given amount of L-Tokens for the same\\n * amount of underlying tokens. It will fail if the contract currently doesn't hold\\n * enough underlying tokens to cover the withdrawal.\\n * @dev In order to save some gas and time to users, frontends should propose this\\n * function to users only when it has been verified that it will not revert. They\\n * should propose the requestWithdrawal() function otherwise.\\n * @param amount The amount L-Tokens to withdraw.\\n */\\n function instantWithdrawal(uint256 amount) external whenNotPaused notBlacklisted(_msgSender()) {\\n // Ensure the account has enough L-Tokens to withdraw\\n require(amount <= balanceOf(_msgSender()), \\\"L48\\\");\\n\\n // Can the contract cover this withdrawal plus all already queued requests?\\n bool cond1 = totalQueued + amount <= usableUnderlyings;\\n\\n // Is caller eligible to staking tier 2 and the contract can cover this withdrawal?\\n bool cond2 = ldyStaking.tierOf(_msgSender()) >= 2 && amount <= usableUnderlyings;\\n\\n // Revert if conditions are not met for the withdrawal to be processed instantaneously\\n if (!(cond1 || cond2)) revert(\\\"L49\\\");\\n\\n // Else, retrieve withdrawal fees and net withdrawn amount\\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(_msgSender(), amount);\\n\\n // Increase unclaimed fees amount accordingly\\n unclaimedFees += fees;\\n\\n // Decrease usable underlyings balance accordingly\\n usableUnderlyings -= withdrawnAmount;\\n\\n // Inform listeners of this instant withdrawal activity event\\n emit ActivityEvent(\\n NO_ID,\\n _msgSender(),\\n Action.Withdraw,\\n amount,\\n withdrawnAmount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Burn withdrawal fees from the account\\n _burn(_msgSender(), fees);\\n\\n // Burn account's withdrawn L-Tokens and transfer to it underlying tokens in a 1:1 ratio\\n super.withdrawTo(_msgSender(), withdrawnAmount);\\n }\\n\\n /**\\n * @notice Allows requesting the exchange of a given amount of L-Tokens for the same\\n * amount of underlying tokens. The request will be automatically processed later.\\n * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees\\n * paid by the withdrawer wallet.\\n * @param amount The amount L-Tokens to withdraw.\\n */\\n function requestWithdrawal(\\n uint256 amount\\n ) public payable whenNotPaused notBlacklisted(_msgSender()) {\\n // Ensure the account has enough L-Tokens to withdraw\\n require(amount <= balanceOf(_msgSender()), \\\"L53\\\");\\n\\n // Ensure the requested amount doesn't overflow uint96\\n require(amount <= type(uint96).max, \\\"L54\\\");\\n\\n // Ensure the sender attached the pre-paid processing gas fees\\n require(msg.value == 0.003 * 10 ** 18, \\\"L55\\\");\\n\\n // Create withdrawal request data\\n WithdrawalRequest memory request = WithdrawalRequest({\\n account: _msgSender(),\\n amount: uint96(amount)\\n });\\n\\n // Will hold the request ID\\n uint256 requestId;\\n\\n // Append request to the withdrawal queue:\\n // - At the beginning, if account is eligible to staking tier 2 and cursor is not 0\\n if (ldyStaking.tierOf(_msgSender()) >= 2 && withdrawalQueueCursor > 0) {\\n withdrawalQueueCursor--;\\n requestId = withdrawalQueueCursor;\\n withdrawalQueue[requestId] = request;\\n }\\n // - At the end else\\n else {\\n withdrawalQueue.push(request);\\n requestId = withdrawalQueue.length - 1;\\n }\\n\\n // Increase total amount queued accordingly\\n totalQueued += amount;\\n\\n // Inform listeners of this new queued withdrawal activity event\\n emit ActivityEvent(\\n int256(requestId),\\n _msgSender(),\\n Action.Withdraw,\\n amount,\\n amount,\\n Status.Queued,\\n NO_ID\\n );\\n\\n // Burn withdrawal L-Tokens amount from account's balance\\n _burn(_msgSender(), amount);\\n\\n // Forward pre-paid processing gas fees to the withdrawer wallet\\n (bool sent, ) = withdrawer.call{value: msg.value}(\\\"\\\");\\n require(sent, \\\"L56\\\");\\n }\\n\\n /**\\n * @notice Processes queued withdrawal requests until there is else no more requests,\\n * else not enough underlying tokens to continue.\\n * @dev For further details, see \\\"LToken > Withdrawals\\\" section of whitepaper.\\n */\\n function processQueuedRequests() external onlyWithdrawer whenNotPaused {\\n // Accumulators variables, will be written on-chain after the loop\\n uint256 cumulatedFees = 0;\\n uint256 cumulatedWithdrawnAmount = 0;\\n uint256 nextRequestId = withdrawalQueueCursor;\\n\\n // Cache queue length to avoid multiple SLOADs and avoid infinite loop as big\\n // requests are increasing the queue length when moved at the end of the queue.\\n uint256 queueLength = withdrawalQueue.length;\\n\\n // Iterate over requests to be processed\\n while (nextRequestId < queueLength) {\\n // Stop processing requests if there is not enough gas left to continue the\\n // loop and properly end the function call. This prevents an attacker from\\n // blocking the withdrawal processing by creating a ton of tiny requests so\\n // this function call cannot fit anymore in block gas limit.\\n if (gasleft() < 45000) break;\\n\\n // Retrieve request data\\n WithdrawalRequest memory request = withdrawalQueue[nextRequestId];\\n\\n // Skip empty request (processed big requests or cancelled requests)\\n if (request.account == address(0)) {}\\n //\\n // If account has been blacklisted since request emission\\n else if (isBlacklisted(request.account)) {\\n // Remove request from queue\\n delete withdrawalQueue[nextRequestId];\\n\\n // Append request in the frozen requests list\\n frozenRequests.push(request);\\n }\\n //\\n // Or if request is a big request, move it at the end of the queue for now.\\n // This request will be processed manually later using processBigQueuedRequest()\\n else if (request.amount > getExpectedRetained() / 2) {\\n // Inform listeners of this queued request being moved at the end of the queue\\n emit ActivityEvent(\\n int256(nextRequestId),\\n _msgSender(),\\n Action.Withdraw,\\n request.amount,\\n request.amount,\\n Status.Moved,\\n int256(withdrawalQueue.length)\\n );\\n\\n // Remove request from queue\\n delete withdrawalQueue[nextRequestId];\\n\\n // Append request at the end of the queue\\n withdrawalQueue.push(request);\\n }\\n //\\n // Else, continue request processing\\n else {\\n // Retrieve withdrawal fees and net withdrawn amount\\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\\n request.account,\\n request.amount\\n );\\n\\n // Break if the contract doesn't hold enough funds to cover the request\\n if (withdrawnAmount > usableUnderlyings - cumulatedWithdrawnAmount) break;\\n\\n // Accumulate fees and withdrawn amount\\n cumulatedFees += fees;\\n cumulatedWithdrawnAmount += withdrawnAmount;\\n\\n // Inform listeners of this queued withdrawal processing activity event\\n emit ActivityEvent(\\n int256(nextRequestId),\\n request.account,\\n Action.Withdraw,\\n request.amount,\\n withdrawnAmount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Remove request from queue\\n delete withdrawalQueue[nextRequestId];\\n\\n // Transfer underlying tokens to account. Burning L-Tokens is not required\\n // as equestWithdrawal() already did it.\\n // Security note: Re-entrancy warning are disabled as the request has\\n // just been deleted from the queue, it will so be skipped if trying to\\n // process it again.\\n // slither-disable-next-line reentrancy-no-eth\\n underlying().safeTransfer(request.account, withdrawnAmount);\\n }\\n\\n // Increment next request ID\\n nextRequestId++;\\n }\\n\\n // Increase unclaimed fees by the amount of cumulated fees\\n unclaimedFees += cumulatedFees;\\n\\n // Decrease usable underlyings by the cumulated amount of withdrawn underlyings\\n usableUnderlyings -= cumulatedWithdrawnAmount;\\n\\n // Decrease total amount queued by the cumulated amount requested\\n totalQueued -= cumulatedWithdrawnAmount + cumulatedFees;\\n\\n // Update new queue cursor\\n withdrawalQueueCursor = nextRequestId;\\n\\n // Retention rate cannot exceeds as the withdrawal decreases both usable\\n // underlyings and expected retained amounts by the same number and as the\\n // expected retained amount is a subset of usable underlyings amount.\\n }\\n\\n /**\\n * @notice Processes a given queued big withdrawal request (one that exceeds half of\\n * the retention rate).\\n * @dev In contrast to non-big requests processing, this function will uses to fund\\n * wallet's balance to fill the request. This allows processing requests that are\\n * greater than retention rate without having to exceed this rate on the contract.\\n * @param requestId The ID of the big request to process.\\n */\\n function processBigQueuedRequest(uint256 requestId) external onlyFund whenNotPaused {\\n // Retrieve request data\\n WithdrawalRequest memory request = withdrawalQueue[requestId];\\n\\n // Ensure the request is active\\n require(request.account != address(0), \\\"L66\\\");\\n\\n // Ensure the request emitter has not been blacklisted since request emission\\n require(!isBlacklisted(request.account), \\\"L50\\\");\\n\\n // Ensure this is indeed a big request\\n require(request.amount > getExpectedRetained() / 2, \\\"L51\\\");\\n\\n // Retrieve withdrawal fees and net withdrawn amount\\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\\n request.account,\\n request.amount\\n );\\n\\n // Ensure withdrawn amount can be covered by contract + fund wallet balances\\n uint256 fundBalance = underlying().balanceOf(fund);\\n require(withdrawnAmount <= usableUnderlyings + fundBalance, \\\"L52\\\");\\n\\n // Increase amount of unclaimed fees accordingly\\n unclaimedFees += fees;\\n\\n // Decrease total queued amount by request amount\\n totalQueued -= request.amount;\\n\\n // Increment queue cursor if request was the next request to be processed\\n if (requestId == withdrawalQueueCursor) withdrawalQueueCursor++;\\n\\n // Inform listeners of this queued withdrawal processing activity event\\n emit ActivityEvent(\\n int256(requestId),\\n request.account,\\n Action.Withdraw,\\n request.amount,\\n withdrawnAmount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Remove request from queue\\n delete withdrawalQueue[requestId];\\n\\n // If fund wallet's balance can cover request, rely on it only\\n if (withdrawnAmount <= fundBalance) {\\n underlying().safeTransferFrom(_msgSender(), request.account, withdrawnAmount);\\n }\\n // Else, cover request from both fund wallet and contract balances\\n else {\\n // Compute amount missing from fund wallet to cover request\\n uint256 missingAmount = withdrawnAmount - fundBalance;\\n\\n // Decrease usable amount of underlying tokens accordingly\\n usableUnderlyings -= missingAmount;\\n\\n // Transfer entire fund balance to request's emitter\\n underlying().safeTransferFrom(_msgSender(), request.account, fundBalance);\\n\\n // Transfer missing amount from contract balance to request emitter\\n underlying().safeTransfer(request.account, missingAmount);\\n }\\n\\n // Transfer exceeding underlying tokens to the fund wallet\\n _transferExceedingToFund();\\n }\\n\\n /**\\n * @notice Cancels a given withdrawal request. The request emitter receive back its\\n * L-Tokens and no fees will be charged.\\n * @param requestId The ID of the withdrawal request to cancel.\\n */\\n function cancelWithdrawalRequest(\\n uint256 requestId\\n ) public whenNotPaused notBlacklisted(_msgSender()) {\\n // Retrieve request data\\n WithdrawalRequest memory request = withdrawalQueue[requestId];\\n\\n // Ensure request belongs to caller\\n require(_msgSender() == request.account, \\\"L57\\\");\\n\\n // Decrease total amount queued accordingly\\n totalQueued -= request.amount;\\n\\n // Delete the withdrawal request from queue\\n delete withdrawalQueue[requestId];\\n\\n // Inform listeners of this cancelled withdrawal request activity event\\n emit ActivityEvent(\\n int256(requestId),\\n request.account,\\n Action.Withdraw,\\n request.amount,\\n request.amount,\\n Status.Cancelled,\\n NO_ID\\n );\\n\\n // Mint back L-Tokens to account\\n _mint(request.account, uint256(request.amount));\\n }\\n\\n /**\\n * @notice Used by the fund wallet to repatriate underlying tokens on the contract\\n * whenever those are required to fulfill some withdrawal requests.\\n * @dev The function will revert if repatriated amount makes the contract exceeding\\n * the retention rate.\\n * @param amount The amount of underlying tokens to repatriate.\\n */\\n function repatriate(uint256 amount) external onlyFund whenNotPaused {\\n // Ensure the fund wallet has enough funds to repatriate\\n require(amount <= underlying().balanceOf(fund), \\\"L58\\\");\\n\\n // Calculate new contract usable balance\\n uint256 newBalance = usableUnderlyings + amount;\\n\\n // Ensure the new balance doesn't exceed the retention rate\\n require(newBalance <= getExpectedRetained(), \\\"L59\\\");\\n\\n // Increase usable underlyings amount by repatriated amount\\n usableUnderlyings += amount;\\n\\n // Transfer amount from fund wallet to contract\\n underlying().safeTransferFrom(_msgSender(), address(this), amount);\\n }\\n\\n /// @notice Used by owner to claim fees generated from successful withdrawals.\\n function claimFees() external onlyOwner {\\n // Ensure there are some fees to claim\\n require(unclaimedFees > 0, \\\"L60\\\");\\n\\n // Ensure the contract holds enough underlying tokens to cover fees\\n require(usableUnderlyings >= unclaimedFees, \\\"L61\\\");\\n\\n // Decrease usable underlyings amount accordingly\\n usableUnderlyings -= unclaimedFees;\\n\\n // Store fees amount in memory and reset unclaimed fees amount\\n uint256 fees = unclaimedFees;\\n unclaimedFees = 0;\\n\\n // Transfer unclaimed fees to owner\\n underlying().safeTransfer(owner(), fees);\\n }\\n}\\n\",\"keccak256\":\"0x03fb59d6d4523deb913cf263137bb0f6d71c5a790aa2ec3556607fcf53184c8e\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalOwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {OwnableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {GlobalOwner} from \\\"../GlobalOwner.sol\\\";\\n\\n/**\\n * @title GlobalOwnableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\\n * contract (see GlobalOwner.sol). This design facilitates centralized management\\n * of ownership for all the Ledgity Yield contracts.\\n *\\n * @dev Note: The _globalOwner state must be set at initialization-time and for evident\\n * security reasons cannot be changed afterwards.\\n *\\n * @dev For further details, see \\\"GlobalOwnableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\\n /**\\n * @notice The GlobalOwner contract the ownership will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalOwner private _globalOwner;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\\n __GlobalOwnable_init_unchained(globalOwner_);\\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\\n // the initial _owner value, calling it would have no effect.\\n }\\n\\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\\n _globalOwner = GlobalOwner(globalOwner_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalOwner contract.\\n * @return The address of the GlobalOwner contract.\\n */\\n function globalOwner() public view returns (address) {\\n return address(_globalOwner);\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\\n * from the GlobalOwner contract instead.\\n * @return The address of the owner\\n */\\n function owner() public view override returns (address) {\\n return _globalOwner.owner();\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\\n * Ownership is managed by the GlobalOwner contract and must be modified there.\\n */\\n function transferOwnership(address newOwner) public view override onlyOwner {\\n newOwner; // Silence unused variable compiler warning\\n revert(\\\"L8\\\");\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\\n * Ownership is managed by the GlobalOwner contract and must be modified there.\\n */\\n function renounceOwnership() public view override onlyOwner {\\n revert(\\\"L65\\\");\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x59c14d38e9e96d4f60cf2fd626c56e23928fce85107ac8d603dfdb90c9d81ec4\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalPausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {GlobalPause} from \\\"../GlobalPause.sol\\\";\\n\\n/**\\n * @title GlobalPausableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit pause state from the specified GlobalPause\\n * contract (see GlobalPause.sol). This design facilitates centralized management of\\n * pause state for all the Ledgity Yield contracts.\\n *\\n * @dev Note: The _globalPause state must be set at initialization-time and for evident\\n * security reasons cannot be changed afterwards.\\n *\\n * @dev For further details, see \\\"GlobalPausableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\\n /**\\n * @notice The GlobalPause contract the pause state will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalPause private _globalPause;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalPause_ The address of the GlobalPause contract.\\n */\\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\\n __Pausable_init();\\n __GlobalPausable_init_unchained(globalPause_);\\n }\\n\\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\\n _globalPause = GlobalPause(globalPause_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalPause contract.\\n * @return The address of the GlobalPause contract.\\n */\\n function globalPause() public view returns (address) {\\n return address(_globalPause);\\n }\\n\\n /**\\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\\n * from the GlobalPause contract instead.\\n * @return Whether the contract is paused or not.\\n */\\n function paused() public view virtual override returns (bool) {\\n return _globalPause.paused();\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x9ab501a2f6256a59e1712576423d4bc2fb97283aee704b87f1b3a749e85d1178\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalRestrictableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalBlacklist} from \\\"../GlobalBlacklist.sol\\\";\\n\\n/**\\n * @title GlobalRestrictableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit blacklist state from the specified\\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\\n * centralized management of a blacklist for all the Ledgity Yield contracts.\\n *\\n * @dev Note: The _globalBlacklist state must be set at initialization-time and for\\n * evident security reasons cannot be changed afterwards.\\n *\\n * @dev For further details, see \\\"GlobalRestrictableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalRestrictableUpgradeable is Initializable {\\n /**\\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalBlacklist private _globalBlacklist;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n */\\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\\n __GlobalRestrictable_init_unchained(globalBlacklist_);\\n }\\n\\n function __GlobalRestrictable_init_unchained(\\n address globalBlacklist_\\n ) internal onlyInitializing {\\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalBlacklist contract.\\n * @return The address of the GlobalBlacklist contract.\\n */\\n function globalBlacklist() public view returns (address) {\\n return address(_globalBlacklist);\\n }\\n\\n /**\\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\\n * @param account Address to verify.\\n */\\n modifier notBlacklisted(address account) {\\n require(isBlacklisted(account) == false, \\\"L9\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\\n * @param account Address to verify.\\n * @return Whether the account is blacklisted.\\n */\\n function isBlacklisted(address account) internal view returns (bool) {\\n return _globalBlacklist.isBlacklisted(account);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xb2413fea06f7221472d88b7d4f9be6e6a4efd8935e0b6857077667e6c881a9ea\",\"license\":\"MIT\"},\"contracts/src/abstracts/InvestUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\n// Contracts\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./GlobalOwnableUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"./GlobalPausableUpgradeable.sol\\\";\\nimport {GlobalRestrictableUpgradeable} from \\\"./GlobalRestrictableUpgradeable.sol\\\";\\nimport \\\"./base/BaseUpgradeable.sol\\\";\\nimport {RecoverableUpgradeable} from \\\"../abstracts/RecoverableUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport {APRHistory as APRH} from \\\"../libs/APRHistory.sol\\\";\\nimport {SUD} from \\\"../libs/SUD.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport {IERC20MetadataUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\n\\n/**\\n * @title InvestUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts are provided with utilities to manage an invested token,\\n * users' investment periods, rewards calculations, virtual balances, and auto-compounding.\\n *\\n * @dev Intuition:\\n * This contract primarily exists for code splitting and reusability. It unburdens the\\n * LToken contract code, making it easier to understand and maintain.\\n *\\n * This contract is generic because it may be used in the LDYStaking contract in the future.\\n *\\n * @dev Definitions:\\n * - Investment: The act of depositing or investing tokens into the contract.\\n * - Investment period: Time between the start of an investment or the last rewards\\n * distribution for an account to the present.\\n * - Virtual balance: Temporary storage for account rewards, used when those can't be\\n * distributed between investment periods.\\n * - Rewards redirection: Mechanism allowing an account to redirect its rewards to another.\\n *\\n * @dev Derived contract must:\\n * - Set invested token during initialization\\n * - Implement _investmentOf() function\\n * - Implement _distributeRewards() function (optional)\\n *\\n * @dev For further details, see \\\"InvestmentUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract InvestUpgradeable is BaseUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n using APRH for APRH.Pack[];\\n\\n /**\\n * @notice Represents an account's investment period.\\n * @param timestamp The timestamp of the most recent rewards distribution.\\n * @param ref The reference of the last APR checkpoint at that timestamp.\\n */\\n struct InvestmentPeriod {\\n uint40 timestamp; // Supports dates up to 20/02/36812\\n APRH.Reference ref;\\n }\\n\\n /**\\n * @notice Represents the investment details of an account.\\n * @param period The current investment period of the account.\\n * @param virtualBalance May hold a part of account rewards until they are claimed.\\n */\\n struct AccountDetails {\\n InvestmentPeriod period;\\n uint256 virtualBalance;\\n }\\n\\n /// @notice Holds a reference to the invested token's contract.\\n IERC20Upgradeable private _invested;\\n\\n /// @notice Holds investment details of each account.\\n mapping(address => AccountDetails) internal accountsDetails;\\n\\n /// @notice Holds an history of the APR value over time (see APRHistory.sol).\\n APRH.Pack[] private _aprHistory;\\n\\n /// @notice Holds active rewards redirections in both from->to and to->from[] ways.\\n mapping(address => address) public rewardsRedirectsFromTo;\\n mapping(address => address[]) public rewardsRedirectsToFrom;\\n\\n /// @notice Is used to prevent infinite loop in _beforeInvestmentChange().\\n bool private _isClaiming;\\n\\n /**\\n * @notice Emitted to inform listeners about a change in the APR's value.\\n * @param newAPRUD7x3 The new APR in UD7x3 format.\\n */\\n event APRChangeEvent(uint16 newAPRUD7x3);\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param invested_ The address of the invested token contract.\\n */\\n function __Invest_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n address invested_\\n ) internal onlyInitializing {\\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\\n __Invest_init_unchained(invested_);\\n }\\n\\n function __Invest_init_unchained(address invested_) internal onlyInitializing {\\n // Set invested token\\n _invested = IERC20Upgradeable(invested_);\\n\\n // Define initial APR to 0%. This would prevent getAPR() from reverting because\\n // of an empty APR history\\n _aprHistory.setAPR(0);\\n }\\n\\n /**\\n * @notice Retrieves the reference to the invested token contract.\\n * @return The reference to the invested token contract.\\n */\\n function invested() public view returns (IERC20Upgradeable) {\\n return _invested;\\n }\\n\\n /**\\n * @notice Updates the investment APR. Restricted to owner.\\n * @param aprUD7x3 The new APR in UD7x3 format.\\n */\\n function setAPR(uint16 aprUD7x3) public onlyOwner {\\n _aprHistory.setAPR(aprUD7x3);\\n emit APRChangeEvent(aprUD7x3);\\n }\\n\\n /**\\n * @notice Retrieves the most recently set APR.\\n * @return The current APR in UD7x3 format.\\n */\\n function getAPR() public view returns (uint16) {\\n return _aprHistory.getAPR();\\n }\\n\\n /**\\n * @notice Enables redirection of rewards from one account to another.\\n * @param from The address of the account to redirect rewards from.\\n * @param to The address of the account to redirect rewards to.\\n */\\n function startRewardsRedirection(\\n address from,\\n address to\\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\\n // Ensure the address is not already redirecting rewards\\n require(rewardsRedirectsFromTo[from] == address(0), \\\"L62\\\");\\n\\n // Ensure neither 'from' nor 'to' are the zero address\\n require(from != address(0), \\\"L12\\\");\\n require(to != address(0), \\\"L13\\\");\\n\\n // Ensure 'from' and 'to' addresses are distinct\\n require(from != to, \\\"L14\\\");\\n\\n // Ensure function caller is either the owner or the 'from' address\\n require(_msgSender() == owner() || _msgSender() == from, \\\"L15\\\");\\n\\n // Distribute current rewards and reset investment periods of both accounts\\n _beforeInvestmentChange(from, true);\\n _beforeInvestmentChange(to, true);\\n\\n // Activate rewards redirection\\n rewardsRedirectsFromTo[from] = to;\\n rewardsRedirectsToFrom[to].push(from);\\n }\\n\\n /**\\n * @notice Disable an active rewards redirection.\\n * @param from The address of the account to stop redirecting rewards from.\\n * @param to The address of the account to stop redirecting rewards to.\\n */\\n function stopRewardsRedirection(\\n address from,\\n address to\\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\\n // Ensure neither 'from' nor 'to' are the zero address\\n require(from != address(0), \\\"L16\\\");\\n require(to != address(0), \\\"L17\\\");\\n\\n // Ensure function caller is either the owner or the 'from' address\\n require(_msgSender() == owner() || _msgSender() == from, \\\"L18\\\");\\n\\n // Ensure a rewards redirection was active\\n require(rewardsRedirectsFromTo[from] == to, \\\"L19\\\");\\n\\n // Distribute current rewards and reset investment periods of both accounts\\n _beforeInvestmentChange(from, true);\\n _beforeInvestmentChange(to, true);\\n\\n // Retrieve 'from' index in the redirection array of 'to'\\n int256 fromIndex = -1;\\n for (uint256 i = 0; i < rewardsRedirectsToFrom[to].length; i++) {\\n if (rewardsRedirectsToFrom[to][i] == from) {\\n fromIndex = int256(i);\\n break;\\n }\\n }\\n\\n // fromIndex should never be -1 at this point\\n assert(fromIndex >= 0);\\n\\n // Deactivate rewards redirection\\n rewardsRedirectsFromTo[from] = address(0);\\n rewardsRedirectsToFrom[to][uint256(fromIndex)] = rewardsRedirectsToFrom[to][\\n rewardsRedirectsToFrom[to].length - 1\\n ];\\n rewardsRedirectsToFrom[to].pop();\\n }\\n\\n /**\\n * @notice Retrieves the total amount of tokens invested by the given account.\\n * @dev Derived contracts must implement this function.\\n * @param account The account to get the investment of.\\n * @return The total amount of tokens invested by the given account.\\n */\\n function _investmentOf(address account) internal view virtual returns (uint256);\\n\\n /**\\n * @notice Distributes a specified amount of rewards to a given account.\\n * @dev Derived contracts may optionally implement this function.\\n * @dev Implementations must return true to indicate a successful distribution, and\\n * false otherwise. If it returns false, the rewards will be added to the account's\\n * virtual balance, in order to be claimed later.\\n * @param account The account to claim the rewards of.\\n * @param amount The amount of rewards to claim.\\n * @return Whether the rewards distribution was successfull.\\n */\\n function _distributeRewards(address account, uint256 amount) internal virtual returns (bool) {\\n account; // Silence unused variables warning\\n amount;\\n return false;\\n }\\n\\n /**\\n * @notice Computes the rewards accrued over a specified period of time, based on a\\n * given APR and amount of invested tokens.\\n * @dev For further details, see \\\"InvestUpgradeable > Rewards calculation\\\" section of\\n * the whitepaper.\\n * @param beginTimestamp The moment the period commenced.\\n * @param endTimestamp The moment the period concluded.\\n * @param aprUD7x3 The APR during this period, in UD7x3 format.\\n * @param investedAmount The amount of tokens deposited/invested during the period.\\n * @return The amount of rewards generated during the period.\\n */\\n function _calculatePeriodRewards(\\n uint40 beginTimestamp,\\n uint40 endTimestamp,\\n uint16 aprUD7x3,\\n uint256 investedAmount\\n ) internal view returns (uint256) {\\n // Cache invested token's decimals number\\n uint256 d = SUD.decimalsOf(address(invested()));\\n\\n // Compute the number of elapsed years\\n uint256 elapsedTimeSUD = SUD.fromInt(endTimestamp - beginTimestamp, d);\\n uint256 elapsedYearsSUD = (elapsedTimeSUD * SUD.fromInt(1, d)) / SUD.fromInt(365 days, d);\\n\\n // Compute the growth in invested amount (thanks to rewards)\\n uint256 aprSUD = SUD.fromRate(aprUD7x3, d);\\n uint256 growthSUD = (elapsedYearsSUD * aprSUD) / SUD.fromInt(1, d);\\n\\n // Compute and return the rewards\\n uint256 investedAmountSUD = SUD.fromAmount(investedAmount, d);\\n uint256 rewardsSUD = (investedAmountSUD * growthSUD) / SUD.fromInt(100, d);\\n return SUD.toAmount(rewardsSUD, d);\\n }\\n\\n /**\\n * @notice Computes the sum of given account's invested amount, plus invested amount\\n * of all accounts that recursively redirect rewards to this account.\\n * @param account The account to calculate the deep investment of.\\n * @return deepInvestedAmount The deep invested amount.\\n */\\n function _deepInvestmentOf(address account) internal view returns (uint256 deepInvestedAmount) {\\n // Consider account's direct investment\\n deepInvestedAmount += _investmentOf(account);\\n\\n // But also the deep investments of all accounts redirecting rewards to this account\\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\\n deepInvestedAmount += _deepInvestmentOf(rewardsRedirectsToFrom[account][i]);\\n }\\n }\\n\\n /**\\n * @notice Computes the amount of unclaimed/undistributed rewards of a given account.\\n * @dev For further details, see \\\"InvestUpgradeable > Rewards calculation\\\" section of\\n * the whitepaper.\\n * @param account The account to calculate the unclaimed rewards of.\\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\\n * @return rewards The amount of unclaimed/undistributed rewards of the given account.\\n */\\n function _rewardsOf(\\n address account,\\n bool autocompound\\n ) internal view returns (uint256 rewards) {\\n // Retrieve account's investment details\\n AccountDetails memory details = accountsDetails[account];\\n\\n // Retrieve account's deep invested amount\\n uint256 investedAmount = _deepInvestmentOf(account);\\n\\n // Return 0 if the account has never invested or has no invested amount\\n if (details.period.timestamp == 0 || investedAmount == 0) return 0;\\n\\n // Retrieve reference and data of APR checkpoint at which started investment period\\n APRH.Reference memory currRef = details.period.ref;\\n APRH.CheckpointData memory currCheckpoint = _aprHistory.getDataFromReference(currRef);\\n\\n // Retrieve reference of latest APR checkpoint\\n APRH.Reference memory latestRef = _aprHistory.getLatestReference();\\n\\n // 1) Fill rewards with virtual balance (rewards not claimed/distributed yet)\\n // See \\\"InvestUpgradeable > Rewards calculation > 1)\\\" section of the whitepaper\\n rewards = details.virtualBalance;\\n\\n // If start checkpoint is not the latest one\\n if (!APRH.eq(currRef, latestRef)) {\\n // Retrieve reference and data of APR checkpoint that comes after start checkpoint\\n APRH.Reference memory nextRef = APRH.incrementReference(currRef);\\n APRH.CheckpointData memory nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\\n\\n // 2) Calculate rewards from investment period start to next checkpoint\\n // See \\\"InvestUpgradeable > Rewards calculation > 2)\\\" section of the whitepaper\\n rewards += _calculatePeriodRewards(\\n details.period.timestamp,\\n nextCheckpoint.timestamp,\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n\\n // 3) Calculate rewards for each crossed pair of checkpoints\\n // See \\\"InvestUpgradeable > Rewards calculation > 3)\\\" section of the whitepaper\\n while (true) {\\n // Set next checkpoint as the current one\\n currRef = nextRef;\\n currCheckpoint = nextCheckpoint;\\n\\n // Break if current checkpoint is the latest one\\n if (APRH.eq(currRef, latestRef)) break;\\n\\n // Else, retrieve the new next checkpoint\\n nextRef = APRH.incrementReference(currRef);\\n nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\\n\\n // Calculate rewards between the current pair of checkpoints\\n rewards += _calculatePeriodRewards(\\n currCheckpoint.timestamp,\\n nextCheckpoint.timestamp,\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n }\\n\\n // 4) Calculate rewards from the latest checkpoint to now\\n // See \\\"InvestUpgradeable > Rewards calculation > 4)\\\" section of the whitepaper\\n rewards += _calculatePeriodRewards(\\n currCheckpoint.timestamp,\\n uint40(block.timestamp),\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n } else {\\n // 2.bis) Calculate rewards from investment period start to now\\n // See \\\"InvestUpgradeable > Rewards calculation > 2.bis)\\\" section of the whitepaper\\n rewards += _calculatePeriodRewards(\\n details.period.timestamp,\\n uint40(block.timestamp),\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n }\\n }\\n\\n /**\\n * @notice Recursively resets the investment period of the specified account and of\\n * all accounts that directly or indirectly redirect rewards to this account.\\n * @param account The account to deeply reset the investment period of.\\n */\\n function _deepResetInvestmentPeriodOf(address account) internal {\\n // Reset account investment period timestamp and APR checkpoint to latest ones\\n accountsDetails[account].period.timestamp = uint40(block.timestamp);\\n accountsDetails[account].period.ref = _aprHistory.getLatestReference();\\n\\n // Also reset the ones of all accounts that recursively redirect rewards to this account\\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\\n _deepResetInvestmentPeriodOf(rewardsRedirectsToFrom[account][i]);\\n }\\n }\\n\\n /**\\n * @notice Hook to be invoked before the invested amount of an account changes. It\\n * ensures that rewards are distributed and that account's investment period is reset.\\n * @param account The account whose invested amount is going to change.\\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\\n */\\n function _beforeInvestmentChange(address account, bool autocompound) internal {\\n // This hook is called inside LToken._beforeTokenTransfer() and as new tokens are\\n // minted in LToken._distributeRewards(), this guards against infinite loop.\\n if (_isClaiming) return;\\n\\n // LToken._beforeTokenTransfer() calls this hook for both involved addresses.\\n // As first call will treat both addresses, the second call would be redundant.\\n // Therefore, we skip accounts already processed in this block to save up some gas.\\n if (accountsDetails[account].period.timestamp == uint40(block.timestamp)) return;\\n\\n // If account redirects its rewards\\n address redirectRewardsTo = rewardsRedirectsFromTo[account];\\n if (redirectRewardsTo != address(0)) {\\n // Call hook on redirection target (this will indirectly reset the investment\\n // of this source account) and return\\n _beforeInvestmentChange(redirectRewardsTo, autocompound);\\n return;\\n }\\n\\n // Else, compute account's undistributed/unclaimed rewards\\n uint256 rewards = _rewardsOf(account, autocompound);\\n\\n // If there are some rewards\\n if (rewards > 0) {\\n // Try to distribute rewards to account\\n _isClaiming = true;\\n bool distributed = _distributeRewards(account, rewards);\\n _isClaiming = false;\\n\\n // If rewards have not been distributed, accumulate them in account's virtual balance\\n if (!distributed) accountsDetails[account].virtualBalance = rewards;\\n }\\n\\n // Finally, deeply reset investment period of the account\\n _deepResetInvestmentPeriodOf(account);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x62af366fd32223f266d27c26fa74b0ba818ef277a62aa27a00f9000531841079\",\"license\":\"MIT\"},\"contracts/src/abstracts/RecoverableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\n// Conracts\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./GlobalOwnableUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @title RecoverableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts are provided with helpers functions that allow recovering\\n * assets accidentally sent to them.\\n *\\n * @dev Note: This abstract contract currently supports only ERC20 tokens. Derived\\n * contracts currently do not implement necessary functions to receive Ether or\\n * ERC721/ERC1155 tokens.\\n *\\n * @dev For further details, see \\\"RecoverableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\\n __GlobalOwnable_init(globalOwner_);\\n __Recoverable_init_unchained();\\n }\\n\\n function __Recoverable_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Recovers a specified amount of a given token address. Will fail if the\\n * contract doesn't hold enough tokens.\\n * @param tokenAddress The address of the token to recover.\\n * @param amount The amount of token to recover.\\n */\\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\\n // Ensure the specified amount is not zero\\n require(amount > 0, \\\"L10\\\");\\n\\n // Create a reference to token's contract\\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\\n\\n // Ensure there is enough token to recover\\n require(tokenContract.balanceOf(address(this)) >= amount, \\\"L11\\\");\\n\\n // Transfer the recovered token amount to the sender\\n tokenContract.safeTransfer(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x00079960b44569f62b9dbccbe7c082b15e13fd769c721fad14c0b2cf36af1a59\",\"license\":\"MIT\"},\"contracts/src/abstracts/base/BaseUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"../GlobalPausableUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"../GlobalOwnableUpgradeable.sol\\\";\\nimport {GlobalRestrictableUpgradeable} from \\\"../GlobalRestrictableUpgradeable.sol\\\";\\nimport {RecoverableUpgradeable} from \\\"../RecoverableUpgradeable.sol\\\";\\n\\n/**\\n * @title BaseUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This abstract contract acts as a base for numerous contracts contract in this\\n * codebase, minimizing code repetition and enhancing readability and maintainability.\\n *\\n * @dev For further details, see \\\"Base\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract BaseUpgradeable is\\n Initializable,\\n UUPSUpgradeable,\\n GlobalOwnableUpgradeable,\\n GlobalPausableUpgradeable,\\n GlobalRestrictableUpgradeable,\\n RecoverableUpgradeable\\n{\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n */\\n function __Base_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_\\n ) internal onlyInitializing {\\n __UUPSUpgradeable_init();\\n __GlobalOwnable_init(globalOwner_);\\n __Pausable_init();\\n __GlobalPausable_init_unchained(globalPause_);\\n __GlobalRestrictable_init_unchained(globalBlacklist_);\\n __Recoverable_init_unchained();\\n }\\n\\n function __Base_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x076f9babfcc47adaa8fbecf462fa1a6f301b0397ddf59c86b6d297608fcf8106\",\"license\":\"MIT\"},\"contracts/src/abstracts/base/ERC20BaseUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {ERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\\\";\\nimport {ERC20PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./BaseUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"../GlobalPausableUpgradeable.sol\\\";\\n\\n/**\\n * @title ERC20BaseUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This abstract contracts is an extension of BaseUpgradeable intended to be used\\n * as a base for ERC20 tokens contracts.\\n *\\n * @dev For further details, see \\\"ERC20BaseUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract ERC20BaseUpgradeable is\\n ERC20Upgradeable,\\n BaseUpgradeable,\\n ERC20PausableUpgradeable\\n{\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param name_ The display name of the token.\\n * @param symbol_ The symbol of the token.\\n */\\n function __ERC20Base_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n string memory name_,\\n string memory symbol_\\n ) internal onlyInitializing {\\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\\n __ERC20_init(name_, symbol_);\\n __ERC20Pausable_init_unchained();\\n }\\n\\n function __ERC20Base_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Required override of paused() which is implemented by both\\n * GlobalPausableUpgradeable and PausableUpgradeable parent contracts.\\n * The GlobalPausableUpgradeable version is preferred because it checks the pause\\n * state from the GlobalPause contract.\\n * @inheritdoc GlobalPausableUpgradeable\\n */\\n function paused()\\n public\\n view\\n virtual\\n override(GlobalPausableUpgradeable, PausableUpgradeable)\\n returns (bool)\\n {\\n return GlobalPausableUpgradeable.paused();\\n }\\n\\n /**\\n * @dev Required override of _beforeTokenTransfer() which is implemented by both\\n * ERC20PausableUpgradeable and ERC20Upgradeable parent contracts.\\n * The ERC20PausableUpgradeable version is preferred because it also checks that\\n * the contract is not paused before allowing the transfer.\\n * @inheritdoc ERC20PausableUpgradeable\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n )\\n internal\\n virtual\\n override(ERC20PausableUpgradeable, ERC20Upgradeable)\\n whenNotPaused\\n notBlacklisted(from)\\n notBlacklisted(to)\\n {\\n ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xf7cbb57bea04cbd394d05a4b216e06c84ba82e35e674042d699a813edd6e50da\",\"license\":\"MIT\"},\"contracts/src/interfaces/ITransfersListener.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\ninterface ITransfersListener {\\n function onLTokenTransfer(address from, address to, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xb71129e8db615bfc1601206027a7056547b997dd2d9aacd9d2aec00508a412c7\",\"license\":\"MIT\"},\"contracts/src/libs/APRHistory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\n/**\\n * @title APRHistory\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This library offers utilities to efficiently maintain on chain, the history of\\n * an APR (Annual Percentage Rate). Each entry in this history is called a \\\"checkpoint\\\".\\n *\\n * @dev Intuition:\\n * Each checkpoint in an APR history consists in two data:\\n * - the creation timestamp\\n * - the APR at that time\\n *\\n * Given that reads and writes to storage slots are among the most costly operations in\\n * Solidity, this library provides a way to store those data on chain in a way that\\n * minimizes the number of used storage slots.\\n *\\n * Instead of storing each checkpoint in a separate storage slot, this library\\n * facilitates the packing of up to 4 checkpoints in a single storage slot.\\n *\\n * @dev Definitions:\\n * - Checkpoint: A record of an APR change\\n * - Pack: A collection of 4 checkpoints stored in a single storage slot\\n * - History: A dynamic array of packs\\n * - Reference: A storage pointer to a checkpoint in the APR history\\n * - CheckpointData: An in-memory representation of a checkpoint data\\n *\\n * @dev Limitation: This library can accommodate APRs only up to 65.536%. This is however\\n * sufficient for APR in LToken contract, which is expected to remain below 10%.\\n *\\n * @dev For further details, see \\\"APRHistory\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nlibrary APRHistory {\\n /**\\n * @notice Represents data of a checkpoint extracted from the on-chain history.\\n * For on-chain representation see \\\"Pack\\\" struct.\\n * @param aprUD7x3 APR in UD7x3 format (e.g., 12345 = 12.345%).\\n * @param timestamp Timestamp of the checkpoint's creation.\\n */\\n struct CheckpointData {\\n uint16 aprUD7x3; // Allows up to 65.536%\\n uint40 timestamp; // Supports dates up to 20/02/36812\\n }\\n\\n /**\\n * @notice Represents how APR checkpoints are stored on chain. Each pack can contain\\n * the data 4 checkpoints. Packs are then stored in a dynamic array (the history).\\n * @param aprsUD7x3 Array of checkpoints' APRs.\\n * @param timestamps Array of checkpoints' timestamps.\\n * @param cursor Index of the next checkpoint to be written.\\n */\\n struct Pack {\\n uint16[4] aprsUD7x3;\\n uint40[4] timestamps;\\n uint32 cursor;\\n }\\n\\n /**\\n * @notice Represents a storage pointer to a specific checkpoint in the history.\\n * @param packIndex Index of the pack the checkpoint belongs to.\\n * @param cursorIndex Index of the checkpoint in this pack (between 0 and 3).\\n */\\n struct Reference {\\n uint256 packIndex;\\n uint32 cursorIndex;\\n }\\n\\n /**\\n * @notice Compares two checkpoints references.\\n * @param ref1 The first reference to compare.\\n * @param ref2 The second reference to compare.\\n * @return Whether the two references points to the same checkpoint.\\n */\\n function eq(Reference memory ref1, Reference memory ref2) external pure returns (bool) {\\n return ref1.packIndex == ref2.packIndex && ref1.cursorIndex == ref2.cursorIndex;\\n }\\n\\n /**\\n * @notice Returns the reference of the checkpoint that should come right after the\\n * referenced checkpoint in the APR history.\\n * @param ref The reference to be incremented.\\n * @return The incremented reference.\\n */\\n function incrementReference(Reference memory ref) public pure returns (Reference memory) {\\n // Ensure cursor index of the given ref is within valid range [0, 3]\\n require(ref.cursorIndex <= 3, \\\"L1\\\");\\n\\n // If the given ref is the last slot in its pack, return ref of next pack's first slot\\n if (ref.cursorIndex == 3) return Reference(ref.packIndex + 1, 0);\\n //\\n // Else, return ref of next slot in current pack\\n else return Reference(ref.packIndex, ref.cursorIndex + 1);\\n }\\n\\n /**\\n * @notice Extracts checkpoint data from a given reference and in APR history.\\n * @param self The APR history to extract the checkpoint from.\\n * @param ref The reference of the checkpoint data to extract.\\n * @return The extracted checkpoint's data.\\n */\\n function getDataFromReference(\\n Pack[] storage self,\\n Reference memory ref\\n ) public view returns (CheckpointData memory) {\\n // Ensure cursor index of the given ref is within valid range [0, 3]\\n require(ref.cursorIndex <= 3, \\\"L2\\\");\\n\\n // Ensure pack index of the given ref exists in history\\n require(ref.packIndex < self.length, \\\"L3\\\");\\n\\n // Retrieve pack data from history\\n Pack memory pack = self[ref.packIndex];\\n\\n // Ensure cursor index of the given ref has been written\\n require(ref.cursorIndex < pack.cursor, \\\"L4\\\");\\n\\n // Build and return the checkpoint data\\n return\\n CheckpointData({\\n aprUD7x3: pack.aprsUD7x3[ref.cursorIndex],\\n timestamp: pack.timestamps[ref.cursorIndex]\\n });\\n }\\n\\n /**\\n * @notice Retrieves the reference to the most recently added checkpoint in the APR history.\\n * @param self The history to extract the reference from.\\n * @return The reference of the latest checkpoint.\\n */\\n function getLatestReference(Pack[] storage self) public view returns (Reference memory) {\\n // Ensure the given history is not empty\\n require(self.length != 0, \\\"L5\\\");\\n\\n // Retrieve latest pack's index and cursor\\n uint256 packIndex = self.length - 1;\\n uint32 packCursor = self[packIndex].cursor;\\n\\n // If this is the first pack ever, ensure it is not empty\\n if (packIndex == 0) require(packCursor != 0, \\\"L6\\\");\\n\\n // If the pack is empty, return ref of previous pack's latest slot\\n if (packCursor == 0) return Reference(packIndex - 1, 3);\\n //\\n // Else, return ref of previous slot in current pack\\n else return Reference(packIndex, packCursor - 1);\\n }\\n\\n /**\\n * @notice Appends a new empty pack to the end of the given APR history array.\\n * @param self The APR history to append an empty to.\\n */\\n function newBlankPack(Pack[] storage self) internal {\\n // If history is not empty, ensure the latest pack is full\\n require(self.length == 0 || getLatestReference(self).cursorIndex == 3, \\\"L7\\\");\\n\\n // Push a new blank pack to the history array\\n self.push(\\n Pack({\\n aprsUD7x3: [uint16(0), uint16(0), uint16(0), uint16(0)],\\n timestamps: [uint40(0), uint40(0), uint40(0), uint40(0)],\\n cursor: 0\\n })\\n );\\n }\\n\\n /**\\n * @notice Write a new APR checkpoint at the end of the given history array.\\n * @param self The array of packs to write the new checkpoint to.\\n * @param aprUD7x3 The new APR in UD7x3 format.\\n */\\n function setAPR(Pack[] storage self, uint16 aprUD7x3) external {\\n // Determine the reference where the new checkpoint should be written\\n Reference memory newRef = self.length == 0\\n ? Reference(0, 0)\\n : incrementReference(getLatestReference(self));\\n\\n // If pack to be written doesn't exist yet, push a new blank pack in history\\n if (newRef.packIndex >= self.length) newBlankPack(self);\\n\\n // Retrieve the pack where the new checkpoint will be stored\\n Pack memory pack = self[newRef.packIndex];\\n\\n // Add new checkpoint's data to the pack\\n pack.aprsUD7x3[newRef.cursorIndex] = aprUD7x3;\\n pack.timestamps[newRef.cursorIndex] = uint40(block.timestamp);\\n\\n // Increment the pack's cursor\\n pack.cursor++;\\n\\n // Write the updated pack in storage\\n self[newRef.packIndex] = pack;\\n }\\n\\n /**\\n * @notice Retrieves the APR of the latest checkpoint written in the APR history.\\n * @param self The history array to read APR from.\\n * @return The latest checkpoint's APR.\\n */\\n function getAPR(Pack[] storage self) public view returns (uint16) {\\n // Retrieve the latest checkpoint data\\n Reference memory ref = getLatestReference(self);\\n CheckpointData memory data = getDataFromReference(self, ref);\\n\\n // Return the latest checkpoint's APR\\n return data.aprUD7x3;\\n }\\n}\\n\",\"keccak256\":\"0x7954e7130fb127fc8cd81fb852de2df2eda688c0d4ef6cdd9280809cdf2815c3\",\"license\":\"MIT\"},\"contracts/src/libs/SUD.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.18;\\n\\nimport {IERC20MetadataUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\n\\n/**\\n * @title SUD\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice SUD serves as an intermediary number format for calculations within this\\n * codebase. It ensures consistency and reduces precision losses. This library\\n * facilitates conversions between various number formats and the SUD format.\\n *\\n * @dev Intuition:\\n * This codebase employs UD (unsigned decimal fixed-point numbers) format to represent\\n * both percentage rates and tokens amounts.\\n *\\n * Rates are expressed in UD7x3 format, whereas the format for tokens amounts depends on\\n * the decimals() value of the involved tokens.\\n *\\n * Three challenges arise from this:\\n * 1) To compute values together, it's essential that they are in the same format\\n * 2) Calculations involving consecutive divisions on UD numbers lead to accumulated\\n * precision loss (because division shrinks). A common approach is to scale up and\\n * down values by a few decimals before and after performing calculations.\\n * 3) Given that rates use the UD7x3 format, if we decided to scale them to and from\\n * the number of decimals of the involved token, 1 to 3 of the rates' decimals would\\n * be shrinked in case token's decimals number is in [0, 2].\\n *\\n * To address these challenges, this library provides the SUD format, which acts as a\\n * consistent and scaled intermediate format to perform calculations on.\\n *\\n * SUD is an acronym for either \\\"Scaled UD\\\" or \\\"Safe UD\\\".\\n *\\n * @dev Definitions:\\n * - Integer: A number without fractional part, e.g., block.timestamp\\n * - UD: A decimal unsigned fixed-point number. The \\\"UD\\\" notation is inspired from\\n * libraries like [prb-math](https://github.com/PaulRBerg/prb-math/)\\n * - Amount: An UD with an unknown (at writing time) repartition of digits between\\n * integral and fractional parts. Represents a token amount.\\n * - Rate: An UD with 7 integral digits and 3 fractional ones (a.k.a UD7x3).\\n * Represents a percentage rate.\\n * - SUD: An UD with 3 more decimals than the involved rate or amount with the highest\\n * decimals number. As rates are represented by UD7x3, a SUD number has at least 6\\n * decimals (3+3) and so ranges from UD71x6 to UD0x77 formats.\\n * Used as an intermediate format to perform calculations.\\n *\\n * @dev This library provides utilities to perform the following conversions:\\n * - Amount <--> SUD\\n * - Rate (UD7x3) <--> SUD\\n * - Integer <--> SUD\\n *\\n * @dev Why scaling by 3 decimals?\\n * - It provides an adequate degree of precision for this codebase,\\n * - It enables the conversion of a UD7x3 rate to SUD format by merely scaling it up by\\n * the involved token's decimal number.\\n *\\n * @dev Optimization note: The functions of this library are not set to external because\\n * incorporating them directly into contracts is more gas-efficient. Given their minimal\\n * size and frequent usage in the InvestUpgradeable, LDYStaking, and LToken contracts,\\n * any bytecode savings from making them external are negated by the additional bytecode\\n * required for external calls to this library.\\n * The can be observed by comparing the output of `pnpm cc:size` when those functions's\\n * visibility is set to external or internal.\\n *\\n * @dev Precision note: While this library mitigates precision loss during calculations\\n * on UD numbers, it's important to note that tokens with lower decimal counts and supply\\n * inherently suffer more from precision loss. Conversely, tokens with higher decimal\\n * counts and supply will experience less precision loss.\\n *\\n * @dev For further details, see \\\"SUD\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nlibrary SUD {\\n /**\\n * @notice Retrieves decimals number of the given ERC20 contract address.\\n * @param tokenAddress The address to retrieve decimals number from.\\n * @return decimals The decimals number of the given ERC20 contract address.\\n */\\n function decimalsOf(address tokenAddress) internal view returns (uint256 decimals) {\\n return IERC20MetadataUpgradeable(tokenAddress).decimals();\\n }\\n\\n /**\\n * @notice Convert a given token amount into SUD format.\\n * @param nAmount The token amount to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nSUD The amount in SUD format\\n */\\n function fromAmount(uint256 nAmount, uint256 decimals) internal pure returns (uint256 nSUD) {\\n // If token decimals < 3, return a UD71x6 number\\n if (decimals < 3) return nAmount * 10 ** (6 - decimals);\\n\\n // Else return a number with decimals+3 fractional digits\\n return nAmount * 10 ** 3;\\n }\\n\\n /**\\n * @notice Convert a given SUD number into token amount format.\\n * @param nSUD The SUD number to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nAmount The number in amount format\\n */\\n function toAmount(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nAmount) {\\n // If token decimals < 3, convert from a UD71x6 number\\n if (decimals < 3) return nSUD / 10 ** (6 - decimals);\\n\\n // Else, convert from a number with decimals+3 fractional digits\\n return nSUD / 10 ** 3;\\n }\\n\\n /**\\n * @notice Converts a given UD7x3 rate into SUD format.\\n * @param nUD7x3 The UD7x3 rate to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nSUD The rate in SUD format.\\n */\\n function fromRate(uint256 nUD7x3, uint256 decimals) internal pure returns (uint256 nSUD) {\\n // If token decimals < 3, return a UD71x6 number\\n if (decimals < 3) return nUD7x3 * 10 ** 3;\\n\\n // Else, return a number with decimals+3 fractional digits\\n return nUD7x3 * 10 ** decimals;\\n }\\n\\n /**\\n * @notice Converts a given SUD number into a UD7x3 rate.\\n * @param nSUD The SUD number to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nUD7x3 The number in UD7x3 rate format.\\n */\\n function toRate(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nUD7x3) {\\n // If token decimals < 3, convert from a UD71x6 number\\n if (decimals < 3) return nSUD / 10 ** 3;\\n\\n // Else, convert from a number with decimals+3 fractional digits\\n return nSUD / 10 ** decimals;\\n }\\n\\n /**\\n * @notice Converts a given integer into SUD format.\\n * @param n The integer to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nSUD The integer in SUD format.\\n */\\n function fromInt(uint256 n, uint256 decimals) internal pure returns (uint256 nSUD) {\\n // If token decimals < 3, return a UD71x6 number\\n if (decimals < 3) return n * 10 ** 6;\\n\\n // Else, return a number with decimals+3 fractional digits\\n return n * 10 ** (decimals + 3);\\n }\\n\\n /**\\n * @notice Converts a given SUD number as an integer (all decimals shrinked).\\n * @param nSUD The SUD number to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return n The SUD number as an integer.\\n */\\n function toInt(uint256 nSUD, uint256 decimals) internal pure returns (uint256 n) {\\n // If token decimals < 3, convert from a UD71x6 number\\n if (decimals < 3) return nSUD / 10 ** 6;\\n\\n // Else, convert from a number with decimals+3 fractional digits\\n return nSUD / 10 ** (decimals + 3);\\n }\\n}\\n\",\"keccak256\":\"0x70c9f9f0ae1875fae1ae6c06a3cd73d405f5a6e2b74493690c044d86acf21f79\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e7565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e5576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615f536200011f60003960008181611462015281816114a2015281816118fd0152818161193d01526119d00152615f536000f3fe6080604052600436106103d95760003560e01c80638980f11f116101fd578063c822adda11610118578063dd62ed3e116100ab578063ef356a791161007a578063ef356a7914610b96578063f12d54d814610bab578063f2fde38b14610bca578063f762e73414610bea578063f94ce2c214610c0957600080fd5b8063dd62ed3e14610b11578063ee1335d114610b31578063ee153c4f14610b51578063ef2591af14610b7157600080fd5b8063d038875c116100e7578063d038875c14610a8d578063d039981b14610ac7578063d294f09314610ae7578063db84faac14610afc57600080fd5b8063c822adda14610a05578063c89d5b8b14610a25578063cafb220214610a4d578063cdc1842414610a6c57600080fd5b8063a457c2d711610190578063b2de2a431161015f578063b2de2a431461097a578063b60d42881461098f578063b6b55f25146109b0578063bacd609e146109d057600080fd5b8063a457c2d7146108fa578063a64c91cc1461091a578063a8f763201461093a578063a9059cbb1461095a57600080fd5b806395d89b41116101cc57806395d89b411461089257806399a03c70146108a75780639c271975146108c75780639ee679e8146108e757600080fd5b80638980f11f146108065780638d8e6bd7146108265780638da5cb5b1461085d57806392e5ced71461087257600080fd5b80634134bee9116102f85780636d3a4ac81161028b578063734d82871161025a578063734d8287146107795780637594d0b51461079057806375a5652b146107a75780637c2edb16146107c75780638370e1f7146107e657600080fd5b80636d3a4ac8146107055780636f307dc31461072557806370a0823114610744578063715018a61461076457600080fd5b806353ac4b66116102c757806353ac4b661461067257806353d3a42f146106895780635c975abb146106d05780635f0e8e37146106e557600080fd5b80634134bee91461060a57806345b05d091461062a5780634f1ef2861461064a57806352d1902d1461065d57600080fd5b806323b872dd116103705780633659cfe61161033f5780633659cfe614610571578063391d85ec1461059157806339509351146105ca5780633e7ae353146105ea57600080fd5b806323b872dd146104f55780632a1b8b1c146105155780632f4f21e21461052a578063313ce5671461054a57600080fd5b80631459457a116103ac5780631459457a1461047b57806318160ddd1461049b5780631c19be6d146104be578063205c2878146104d557600080fd5b806306fdde03146103de578063095ea7b3146104095780630d174c24146104395780630e21750f1461045b575b600080fd5b3480156103ea57600080fd5b506103f3610c29565b6040516104009190615460565b60405180910390f35b34801561041557600080fd5b506104296104243660046154a8565b610cbb565b6040519015158152602001610400565b34801561044557600080fd5b506104596104543660046154d4565b610cd5565b005b34801561046757600080fd5b506104596104763660046154d4565b610d41565b34801561048757600080fd5b506104596104963660046154f1565b610da8565b3480156104a757600080fd5b506104b061100c565b604051908152602001610400565b3480156104ca57600080fd5b506104b06102fe5481565b3480156104e157600080fd5b506104296104f03660046154a8565b611037565b34801561050157600080fd5b50610429610510366004615562565b611068565b34801561052157600080fd5b5061045961108e565b34801561053657600080fd5b506104296105453660046154a8565b61141d565b34801561055657600080fd5b5061055f61144e565b60405160ff9091168152602001610400565b34801561057d57600080fd5b5061045961058c3660046154d4565b611458565b34801561059d57600080fd5b506102f9546105b2906001600160a01b031681565b6040516001600160a01b039091168152602001610400565b3480156105d657600080fd5b506104296105e53660046154a8565b611537565b3480156105f657600080fd5b506105b26106053660046154a8565b611559565b34801561061657600080fd5b506104596106253660046155a3565b611592565b34801561063657600080fd5b506104596106453660046155a3565b611786565b610459610658366004615654565b6118f3565b34801561066957600080fd5b506104b06119c3565b34801561067e57600080fd5b506104b06102fd5481565b34801561069557600080fd5b506106a96106a43660046155a3565b611a76565b604080516001600160a01b0390931683526001600160601b03909116602083015201610400565b3480156106dc57600080fd5b50610429611ab2565b3480156106f157600080fd5b506104596107003660046154d4565b611abc565b34801561071157600080fd5b506104596107203660046156f7565b611c13565b34801561073157600080fd5b506102c6546001600160a01b03166105b2565b34801561075057600080fd5b506104b061075f3660046154d4565b611cc4565b34801561077057600080fd5b50610459611ce2565b34801561078557600080fd5b506104b06102fc5481565b34801561079c57600080fd5b506104b06103005481565b3480156107b357600080fd5b506104596107c23660046155a3565b611d18565b3480156107d357600080fd5b50610193546001600160a01b03166105b2565b3480156107f257600080fd5b506104596108013660046155a3565b6120d4565b34801561081257600080fd5b506104596108213660046154a8565b612258565b34801561083257600080fd5b506105b26108413660046154d4565b610291602052600090815260409020546001600160a01b031681565b34801561086957600080fd5b506105b26122bd565b34801561087e57600080fd5b5061045961088d366004615714565b61232c565b34801561089e57600080fd5b506103f3612563565b3480156108b357600080fd5b506104b06108c23660046154d4565b612572565b3480156108d357600080fd5b506104596108e23660046154d4565b612590565b6104596108f53660046155a3565b6125eb565b34801561090657600080fd5b506104296109153660046154a8565b612952565b34801561092657600080fd5b506104596109353660046154d4565b6129d8565b34801561094657600080fd5b50610459610955366004615714565b612a03565b34801561096657600080fd5b506104296109753660046154a8565b612d39565b34801561098657600080fd5b50610459612d47565b34801561099b57600080fd5b506102fb546105b2906001600160a01b031681565b3480156109bc57600080fd5b506104596109cb3660046155a3565b612e30565b3480156109dc57600080fd5b506109f06109eb3660046154a8565b612f87565b60408051928352602083019190915201610400565b348015610a1157600080fd5b506106a9610a203660046155a3565b6130a3565b348015610a3157600080fd5b50610a3a6130b4565b60405161ffff9091168152602001610400565b348015610a5957600080fd5b5061028e546001600160a01b03166105b2565b348015610a7857600080fd5b506102fa546105b2906001600160a01b031681565b348015610a9957600080fd5b506102fb54610ab290600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610400565b348015610ad357600080fd5b506104b0610ae23660046154d4565b61312c565b348015610af357600080fd5b50610459613139565b348015610b0857600080fd5b506104b06131fa565b348015610b1d57600080fd5b506104b0610b2c366004615714565b613281565b348015610b3d57600080fd5b50610459610b4c36600461575f565b6132ac565b348015610b5d57600080fd5b506105b2610b6c3660046155a3565b6132db565b348015610b7d57600080fd5b506102fb54610ab290600160c01b900463ffffffff1681565b348015610ba257600080fd5b506104b0613306565b348015610bb757600080fd5b50610160546001600160a01b03166105b2565b348015610bd657600080fd5b50610459610be53660046154d4565b613311565b348015610bf657600080fd5b5061012d546001600160a01b03166105b2565b348015610c1557600080fd5b50610459610c2436600461575f565b613346565b6060609a8054610c389061577c565b80601f0160208091040260200160405190810160405280929190818152602001828054610c649061577c565b8015610cb15780601f10610c8657610100808354040283529160200191610cb1565b820191906000526020600020905b815481529060010190602001808311610c9457829003601f168201915b5050505050905090565b600033610cc98185856133b3565b60019150505b92915050565b610cdd6134d7565b6001600160a01b038116610d1e5760405162461bcd60e51b81526020600482015260036024820152624c363360e81b60448201526064015b60405180910390fd5b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055565b610d496134d7565b6001600160a01b038116610d855760405162461bcd60e51b8152602060048201526003602482015262130d8d60ea1b6044820152606401610d15565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1615808015610dc85750600054600160ff909116105b80610de25750303b158015610de2575060005460ff166001145b610e455760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610d15565b6000805460ff191660011790558015610e68576000805461ff0019166101001790555b6000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ea8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed091908101906157b0565b9050610f1d87878784604051602001610ee99190615827565b60405160208183030381529060405285604051602001610f099190615857565b604051602081830303815290604052613538565b610f268361357c565b610f2f306135ac565b6102f980546001600160a01b0319166001600160a01b0386161790556102fb805467ffffffffffffffff60a01b19166509c40000004b60a21b179055610f736122bd565b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055610f9c6122bd565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055508015611004576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b60006102fc546102fd5461101e613306565b6110289190615896565b6110329190615896565b905090565b60405162461bcd60e51b81526020600482015260036024820152624c343560e81b6044820152600090606401610d15565b600033611076858285613656565b6110818585856136d0565b60019150505b9392505050565b6102fa546001600160a01b0316336001600160a01b0316146110d85760405162461bcd60e51b81526020600482015260036024820152624c333960e81b6044820152606401610d15565b6110e061388c565b610300546102ff5460009182915b808210156113c05761afc85a106113c05760006102ff8381548110611115576111156158a9565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150156113ad578051611164906138d4565b156111e6576102ff838154811061117d5761117d6158a9565b60009182526020808320909101829055610301805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177fe78f8e39db67a8c6e0d54c288efc6f296f5d558bc028138a8476c9b97f6fcaa4909101556113ad565b60026111f06131fa565b6111fa91906158bf565b81602001516001600160601b031611156112c65760208101516102ff5460405160019233928792600080516020615efe833981519152926112419290918291600391615903565b60405180910390a46102ff838154811061125d5761125d6158a9565b600091825260208083209091018290556102ff805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec909101556113ad565b6000806112e4836000015184602001516001600160601b0316612f87565b91509150856102fe546112f79190615937565b821115611306575050506113c0565b6113108188615896565b965061131c8287615896565b9550600183600001516001600160a01b031686600080516020615efe8339815191528660200151866002600019604051611359949392919061594a565b60405180910390a46102ff8581548110611375576113756158a9565b600091825260208220015582516113aa908361139a6102c6546001600160a01b031690565b6001600160a01b03169190613944565b50505b826113b78161596e565b935050506110ee565b836102fc60008282546113d39190615896565b92505081905550826102fe60008282546113ed9190615937565b909155506113fd90508484615896565b6102fd600082825461140f9190615937565b909155505050610300555050565b60405162461bcd60e51b8152602060048201526003602482015262261a1b60e91b6044820152600090606401610d15565b60006110326139a7565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036114a05760405162461bcd60e51b8152600401610d1590615987565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166114e9600080516020615eb7833981519152546001600160a01b031690565b6001600160a01b03161461150f5760405162461bcd60e51b8152600401610d15906159d3565b61151881613a1d565b6040805160008082526020820190925261153491839190613a25565b50565b600033610cc981858561154a8383613281565b6115549190615896565b6133b3565b610292602052816000526040600020818154811061157657600080fd5b6000918252602090912001546001600160a01b03169150829050565b61159a61388c565b336115a4816138d4565b156115c15760405162461bcd60e51b8152600401610d1590615a1f565b6115ca33611cc4565b8211156115ff5760405162461bcd60e51b815260206004820152600360248201526209868760eb1b6044820152606401610d15565b60006102fe54836102fd546116149190615896565b6102f95491101591506000906002906001600160a01b031663c8f74bb8336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169a9190615a3b565b101580156116ab57506102fe548411155b905081806116b65750805b6116e85760405162461bcd60e51b81526020600482015260036024820152624c343960e81b6044820152606401610d15565b6000806116f53387612f87565b91509150806102fc600082825461170c9190615896565b92505081905550816102fe60008282546117269190615937565b9091555060019050336001600160a01b0316600019600080516020615efe833981519152898660026000196040516117619493929190615a54565b60405180910390a46117733382613b90565b61177d3383613cd7565b50505050505050565b61178e61388c565b33611798816138d4565b156117b55760405162461bcd60e51b8152600401610d1590615a1f565b60006102ff83815481106117cb576117cb6158a9565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150336001600160a01b0316146118475760405162461bcd60e51b81526020600482015260036024820152624c353760e81b6044820152606401610d15565b80602001516001600160601b03166102fd60008282546118679190615937565b90915550506102ff805484908110611881576118816158a9565b6000918252602082200155600181600001516001600160a01b031684600080516020615efe8339815191528460200151856020015160016000196040516118cb9493929190615903565b60405180910390a46118ee816000015182602001516001600160601b0316613d04565b505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361193b5760405162461bcd60e51b8152600401610d1590615987565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611984600080516020615eb7833981519152546001600160a01b031690565b6001600160a01b0316146119aa5760405162461bcd60e51b8152600401610d15906159d3565b6119b382613a1d565b6119bf82826001613a25565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a635760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610d15565b50600080516020615eb783398151915290565b6103018181548110611a8757600080fd5b6000918252602090912001546001600160a01b0381169150600160a01b90046001600160601b031682565b6000611032613dd9565b611ac46134d7565b610302546000199060005b81811015611b2957836001600160a01b03166103028281548110611af557611af56158a9565b6000918252602090912001546001600160a01b031603611b1757809250611b29565b80611b218161596e565b915050611acf565b506000198213611b615760405162461bcd60e51b8152602060048201526003602482015262261a1960e91b6044820152606401610d15565b610302611b6f600183615937565b81548110611b7f57611b7f6158a9565b60009182526020909120015461030280546001600160a01b039092169184908110611bac57611bac6158a9565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550610302805480611bec57611bec615a6f565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b611c1b6134d7565b60405163433e3bad60e11b8152610290600482015261ffff82166024820152733F0Ff9947550d7Cf26549136552C785446ad4Ac59063867c775a9060440160006040518083038186803b158015611c7157600080fd5b505af4158015611c85573d6000803e3d6000fd5b505060405161ffff841681527f3d6d63f501ae621a01c729938fb4428a25138835257943d6b56c49b402ba36329250602001905060405180910390a150565b6000611ccf8261312c565b611cd883612572565b610ccf9190615896565b611cea6134d7565b60405162461bcd60e51b81526020600482015260036024820152624c363560e81b6044820152606401610d15565b6102fb546001600160a01b0316336001600160a01b031614611d625760405162461bcd60e51b815260206004820152600360248201526204c34360ec1b6044820152606401610d15565b611d6a61388c565b60006102ff8281548110611d8057611d806158a9565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150611df15760405162461bcd60e51b8152602060048201526003602482015262261b1b60e91b6044820152606401610d15565b8051611dfc906138d4565b15611e2f5760405162461bcd60e51b815260206004820152600360248201526204c35360ec1b6044820152606401610d15565b6002611e396131fa565b611e4391906158bf565b81602001516001600160601b031611611e845760405162461bcd60e51b81526020600482015260036024820152624c353160e81b6044820152606401610d15565b600080611ea2836000015184602001516001600160601b0316612f87565b915091506000611ebb6102c6546001600160a01b031690565b6102fb546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa158015611f05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f299190615a3b565b9050806102fe54611f3a9190615896565b831115611f6f5760405162461bcd60e51b8152602060048201526003602482015262261a9960e91b6044820152606401610d15565b816102fc6000828254611f829190615896565b9250508190555083602001516001600160601b03166102fd6000828254611fa99190615937565b9091555050610300548503611fcf576103008054906000611fc98361596e565b91905055505b600184600001516001600160a01b031686600080516020615efe833981519152876020015187600260001960405161200a949392919061594a565b60405180910390a46102ff8581548110612026576120266158a9565b600091825260208220015580831161206857612063338551856120526102c6546001600160a01b031690565b6001600160a01b0316929190613e48565b6120c5565b60006120748285615937565b9050806102fe60008282546120899190615937565b909155506120a99050338651846120526102c6546001600160a01b031690565b84516120c3908261139a6102c6546001600160a01b031690565b505b6120cd613e80565b5050505050565b6102fb546001600160a01b0316336001600160a01b03161461211e5760405162461bcd60e51b815260206004820152600360248201526204c34360ec1b6044820152606401610d15565b61212661388c565b6102c6546001600160a01b03166102fb546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa15801561217d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a19190615a3b565b8111156121d65760405162461bcd60e51b81526020600482015260036024820152620986a760eb1b6044820152606401610d15565b6000816102fe546121e79190615896565b90506121f16131fa565b8111156122265760405162461bcd60e51b81526020600482015260036024820152624c353960e81b6044820152606401610d15565b816102fe60008282546122399190615896565b909155506119bf90503330846120526102c6546001600160a01b031690565b6122606134d7565b6102c6546001600160a01b03166001600160a01b0316826001600160a01b0316036122b35760405162461bcd60e51b81526020600482015260036024820152624c343360e81b6044820152606401610d15565b6119bf8282613ee9565b61012d5460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015612308573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615a85565b61233461388c565b8161233e816138d4565b1561235b5760405162461bcd60e51b8152600401610d1590615a1f565b81612365816138d4565b156123825760405162461bcd60e51b8152600401610d1590615a1f565b6001600160a01b038481166000908152610291602052604090205416156123d15760405162461bcd60e51b8152602060048201526003602482015262261b1960e91b6044820152606401610d15565b6001600160a01b03841661240d5760405162461bcd60e51b815260206004820152600360248201526226189960e91b6044820152606401610d15565b6001600160a01b0383166124495760405162461bcd60e51b81526020600482015260036024820152624c313360e81b6044820152606401610d15565b826001600160a01b0316846001600160a01b0316036124905760405162461bcd60e51b8152602060048201526003602482015262130c4d60ea1b6044820152606401610d15565b6124986122bd565b6001600160a01b0316336001600160a01b031614806124bf5750336001600160a01b038516145b6124f15760405162461bcd60e51b81526020600482015260036024820152624c313560e81b6044820152606401610d15565b6124fc846001613fdb565b612507836001613fdb565b50506001600160a01b039182166000818152610291602090815260408083208054969095166001600160a01b03199687168117909555938252610292815292812080546001810182559082529290209091018054909216179055565b6060609b8054610c389061577c565b6001600160a01b038116600090815260976020526040812054610ccf565b6125986134d7565b61030280546001810182556000919091527f552430c2010355dda19e8bae437f75cfb136cb8d667c4c0867367db21eee69b60180546001600160a01b0319166001600160a01b0392909216919091179055565b6125f361388c565b336125fd816138d4565b1561261a5760405162461bcd60e51b8152600401610d1590615a1f565b61262333611cc4565b8211156126585760405162461bcd60e51b81526020600482015260036024820152624c353360e81b6044820152606401610d15565b6001600160601b038211156126955760405162461bcd60e51b8152602060048201526003602482015262130d4d60ea1b6044820152606401610d15565b34660aa87bee538000146126d15760405162461bcd60e51b81526020600482015260036024820152624c353560e81b6044820152606401610d15565b600060405180604001604052806126e53390565b6001600160a01b0390811682526001600160601b0386166020909201919091526102f9549192506000916002911663c8f74bb8336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561275d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127819190615a3b565b101580156127925750600061030054115b156128005761030080549060006127a883615aa2565b9190505550610300549050816102ff82815481106127c8576127c86158a9565b6000918252602091829020835193909201516001600160601b0316600160a01b026001600160a01b039093169290921791015561286a565b6102ff8054600181810183556000839052845160208601516001600160601b0316600160a01b026001600160a01b03909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec9092019190915590546128679190615937565b90505b836102fd600082825461287d9190615896565b9091555060019050336001600160a01b031682600080516020615efe833981519152878860006000196040516128b69493929190615a54565b60405180910390a46128c83385613b90565b6102fa546040516000916001600160a01b03169034908381818185875af1925050503d8060008114612916576040519150601f19603f3d011682016040523d82523d6000602084013e61291b565b606091505b50509050806120cd5760405162461bcd60e51b8152602060048201526003602482015262261a9b60e91b6044820152606401610d15565b600033816129608286613281565b9050838110156129c05760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610d15565b6129cd82868684036133b3565b506001949350505050565b6129e06134d7565b6102f980546001600160a01b0319166001600160a01b0392909216919091179055565b612a0b61388c565b81612a15816138d4565b15612a325760405162461bcd60e51b8152600401610d1590615a1f565b81612a3c816138d4565b15612a595760405162461bcd60e51b8152600401610d1590615a1f565b6001600160a01b038416612a955760405162461bcd60e51b815260206004820152600360248201526226189b60e91b6044820152606401610d15565b6001600160a01b038316612ad15760405162461bcd60e51b81526020600482015260036024820152624c313760e81b6044820152606401610d15565b612ad96122bd565b6001600160a01b0316336001600160a01b03161480612b005750336001600160a01b038516145b612b325760405162461bcd60e51b815260206004820152600360248201526209862760eb1b6044820152606401610d15565b6001600160a01b0384811660009081526102916020526040902054811690841614612b855760405162461bcd60e51b81526020600482015260036024820152624c313960e81b6044820152606401610d15565b612b90846001613fdb565b612b9b836001613fdb565b60001960005b6001600160a01b03851660009081526102926020526040902054811015612c26576001600160a01b0385811660009081526102926020526040902080549188169183908110612bf257612bf26158a9565b6000918252602090912001546001600160a01b031603612c1457809150612c26565b80612c1e8161596e565b915050612ba1565b506000811215612c3857612c38615ab9565b6001600160a01b0380861660009081526102916020908152604080832080546001600160a01b031916905592871682526102929052208054612c7c90600190615937565b81548110612c8c57612c8c6158a9565b60009182526020808320909101546001600160a01b0387811684526102929092526040909220805491909216919083908110612cca57612cca6158a9565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918616815261029290915260409020805480612d1057612d10615a6f565b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b600033610cc98185856136d0565b612d4f6134d7565b60006102fe54612d686102c6546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd29190615a3b565b612ddc9190615937565b905060008111612e145760405162461bcd60e51b8152602060048201526003602482015262130d0d60ea1b6044820152606401610d15565b611534612e2a6102c6546001600160a01b031690565b82613ee9565b612e3861388c565b33612e42816138d4565b15612e5f5760405162461bcd60e51b8152600401610d1590615a1f565b81612e736102c6546001600160a01b031690565b6001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eea9190615a3b565b1015612f1e5760405162461bcd60e51b81526020600482015260036024820152624c343760e81b6044820152606401610d15565b816102fe6000828254612f319190615896565b9091555060009050336001600160a01b0316600019600080516020615efe83398151915285866002600019604051612f6c9493929190615a54565b60405180910390a4612f7e33836140b0565b506119bf613e80565b6102f95460405163191ee97760e31b81526001600160a01b03848116600483015260009283926002929091169063c8f74bb890602401602060405180830381865afa158015612fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffe9190615a3b565b1061300e5750819050600061309c565b600061302b61302661028e546001600160a01b031690565b614131565b90506000613039858361419e565b6102fb5490915060009061305a90600160a01b900463ffffffff16846141dc565b90506000613069606485614208565b6130738385615acf565b61307d91906158bf565b90506130898185614236565b94506130958588615937565b9550505050505b9250929050565b6102ff8181548110611a8757600080fd5b60405163106d64cf60e31b81526102906004820152600090733F0Ff9947550d7Cf26549136552C785446ad4Ac59063836b267890602401602060405180830381865af4158015613108573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615ae6565b6000610ccf82600161426d565b6131416134d7565b60006102fc541161317a5760405162461bcd60e51b815260206004820152600360248201526204c36360ec1b6044820152606401610d15565b6102fc546102fe5410156131b65760405162461bcd60e51b81526020600482015260036024820152624c363160e81b6044820152606401610d15565b6102fc546102fe60008282546131cc9190615937565b90915550506102fc805460009091556115346131e66122bd565b8261139a6102c6546001600160a01b031690565b60008061321361302661028e546001600160a01b031690565b9050600061322861322261100c565b8361419e565b6102fb5490915060009061324990600160c01b900463ffffffff16846141dc565b90506000613258606485614208565b6132628385615acf565b61326c91906158bf565b90506132788185614236565b94505050505090565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6132b46134d7565b6102fb805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b61030281815481106132ec57600080fd5b6000918252602090912001546001600160a01b0316905081565b600061103260995490565b6133196134d7565b60405162461bcd60e51b8152602060048201526002602482015261098760f31b6044820152606401610d15565b61334e6134d7565b61271063ffffffff8216111561338c5760405162461bcd60e51b81526020600482015260036024820152624c343160e81b6044820152606401610d15565b6102fb805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b6001600160a01b0383166134155760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610d15565b6001600160a01b0382166134765760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610d15565b6001600160a01b0383811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b336134e06122bd565b6001600160a01b0316146135365760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d15565b565b600054610100900460ff1661355f5760405162461bcd60e51b8152600401610d1590615b03565b61356a8585856147d3565b613574828261482d565b6120cd61485e565b600054610100900460ff166135a35760405162461bcd60e51b8152600401610d1590615b03565b61153481614885565b600054610100900460ff166135d35760405162461bcd60e51b8152600401610d1590615b03565b61028e80546001600160a01b0319166001600160a01b03831617905560405163433e3bad60e11b8152610290600482015260006024820152733F0Ff9947550d7Cf26549136552C785446ad4Ac59063867c775a9060440160006040518083038186803b15801561364257600080fd5b505af41580156120cd573d6000803e3d6000fd5b60006136628484613281565b905060001981146136ca57818110156136bd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610d15565b6136ca84848484036133b3565b50505050565b6001600160a01b0383166137345760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610d15565b6001600160a01b0382166137965760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610d15565b6137a1838383614927565b6001600160a01b038316600090815260976020526040902054818110156138195760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610d15565b6001600160a01b0380851660008181526097602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906138799086815260200190565b60405180910390a36136ca848484614966565b613894611ab2565b156135365760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610d15565b6101935460405163fe575a8760e01b81526001600160a01b038381166004830152600092169063fe575a8790602401602060405180830381865afa158015613920573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccf9190615b4e565b6040516001600160a01b0383166024820152604481018290526118ee90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614a6f565b6102c6546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048083019260209291908290030181865afa925050508015613a0e575060408051601f3d908101601f19168201909252613a0b91810190615b70565b60015b613a185750601290565b919050565b6115346134d7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615613a58576118ee83614b44565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613ab2575060408051601f3d908101601f19168201909252613aaf91810190615a3b565b60015b613b155760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610d15565b600080516020615eb78339815191528114613b845760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610d15565b506118ee838383614be0565b6001600160a01b038216613bf05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610d15565b613bfc82600083614927565b6001600160a01b03821660009081526097602052604090205481811015613c705760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610d15565b6001600160a01b03831660008181526097602090815260408083208686039055609980548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36118ee83600084614966565b6000613ce33383613b90565b6102c654613cfb906001600160a01b03168484613944565b50600192915050565b6001600160a01b038216613d5a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610d15565b613d6660008383614927565b8060996000828254613d789190615896565b90915550506001600160a01b0382166000818152609760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36119bf60008383614966565b6101605460408051635c975abb60e01b815290516000926001600160a01b031691635c975abb9160048083019260209291908290030181865afa158015613e24573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615b4e565b6040516001600160a01b03808516602483015283166044820152606481018290526136ca9085906323b872dd60e01b90608401613970565b6000613e8a6131fa565b9050806102fe5411613e995750565b6000816102fe54613eaa9190615937565b9050806102fe6000828254613ebf9190615937565b90915550506102fb546119bf906001600160a01b03168261139a6102c6546001600160a01b031690565b613ef16134d7565b60008111613f275760405162461bcd60e51b815260206004820152600360248201526204c31360ec1b6044820152606401610d15565b6040516370a0823160e01b8152306004820152829082906001600160a01b038316906370a0823190602401602060405180830381865afa158015613f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f939190615a3b565b1015613fc75760405162461bcd60e51b81526020600482015260036024820152624c313160e81b6044820152606401610d15565b6118ee6001600160a01b0382163384613944565b6102935460ff1615613feb575050565b6001600160a01b038216600090815261028f602052604090205464ffffffffff428116911603614019575050565b6001600160a01b0380831660009081526102916020526040902054168015614045576118ee8183613fdb565b6000614051848461426d565b905080156140a757610293805460ff1916600117905560006140738583614c05565b610293805460ff191690559050806140a5576001600160a01b038516600090815261028f602052604090206003018290555b505b6136ca84614c5c565b60003330810361410e5760405162461bcd60e51b815260206004820152602360248201527f4552433230577261707065723a20777261707065722063616e2774206465706f6044820152621cda5d60ea1b6064820152608401610d15565b6102c654614127906001600160a01b0316823086613e48565b610cc98484613d04565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141959190615b70565b60ff1692915050565b600060038210156141d0576141b4826006615937565b6141bf90600a615c77565b6141c99084615acf565b9050610ccf565b611087836103e8615acf565b600060038210156141f3576141c9836103e8615acf565b6141fe82600a615c77565b6110879084615acf565b60006003821015614220576141c983620f4240615acf565b61422b826003615896565b6141fe90600a615c77565b600060038210156142615761424c826006615937565b61425790600a615c77565b6141c990846158bf565b6110876103e8846158bf565b6001600160a01b038216600090815261028f602090815260408083208151608081018352815464ffffffffff16818401908152835180850190945260018301548452600283015463ffffffff168486015260608201939093529182526003015491810191909152816142de85614dbe565b82515190915064ffffffffff1615806142f5575080155b1561430557600092505050610ccf565b815160200151604051630b27cfb160e31b8152600090733F0Ff9947550d7Cf26549136552C785446ad4Ac59063593e7d889061434990610290908690600401615c83565b6040805180830381865af4158015614365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143899190615ca7565b60405163038255fd60e11b81526102906004820152909150600090733F0Ff9947550d7Cf26549136552C785446ad4Ac590630704abfa906024016040805180830381865af41580156143df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144039190615cf2565b905084602001519550733F0Ff9947550d7Cf26549136552C785446ad4Ac5634ead0c5384836040518363ffffffff1660e01b8152600401614445929190615d1e565b602060405180830381865af4158015614462573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144869190615b4e565b61479757604051633e1e5c5360e11b8152600090733F0Ff9947550d7Cf26549136552C785446ad4Ac590637c3cb8a6906144c4908790600401615d52565b6040805180830381865af41580156144e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145049190615cf2565b604051630b27cfb160e31b8152909150600090733F0Ff9947550d7Cf26549136552C785446ad4Ac59063593e7d889061454590610290908690600401615c83565b6040805180830381865af4158015614561573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145859190615ca7565b875151602082015186519293506145b3928c6145a25760006145a4565b8b5b6145ae908b615896565b614e67565b6145bd9089615896565b97505b819450809350733F0Ff9947550d7Cf26549136552C785446ad4Ac5634ead0c5386856040518363ffffffff1660e01b81526004016145ff929190615d1e565b602060405180830381865af415801561461c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146409190615b4e565b61476a57604051633e1e5c5360e11b8152733F0Ff9947550d7Cf26549136552C785446ad4Ac590637c3cb8a69061467b908890600401615d52565b6040805180830381865af4158015614697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146bb9190615cf2565b604051630b27cfb160e31b8152909250733F0Ff9947550d7Cf26549136552C785446ad4Ac59063593e7d88906146f990610290908690600401615c83565b6040805180830381865af4158015614715573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147399190615ca7565b90506147598460200151826020015186600001518c6145a25760006145a4565b6147639089615896565b97506145c0565b61478484602001514286600001518c6145a25760006145a4565b61478e9089615896565b975050506147c8565b84515182516147bb919042908a6147af5760006147b1565b895b6145ae9089615896565b6147c59087615896565b95505b505050505092915050565b600054610100900460ff166147fa5760405162461bcd60e51b8152600401610d1590615b03565b61480261485e565b61480b83614f53565b614813614f83565b61481c82614fb2565b61482581614ffc565b6118ee61485e565b600054610100900460ff166148545760405162461bcd60e51b8152600401610d1590615b03565b6119bf8282615046565b600054610100900460ff166135365760405162461bcd60e51b8152600401610d1590615b03565b600054610100900460ff166148ac5760405162461bcd60e51b8152600401610d1590615b03565b306001600160a01b038216036149045760405162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a2063616e6e6f742073656c66207772617000006044820152606401610d15565b6102c680546001600160a01b0319166001600160a01b0392909216919091179055565b614932838383615086565b6001600160a01b0383161561494c5761494c836001613fdb565b6001600160a01b038216156118ee576118ee826001613fdb565b6001600160a01b038316158061498357506001600160a01b038216155b156149c3577f980f7e6fb44009001d533a10bc3bd558b4efe22dcb4888bca4767aa93c71ce1f6149b161100c565b60405190815260200160405180910390a15b60005b610302548110156136ca5761030281815481106149e5576149e56158a9565b600091825260209091200154604051636e0d037d60e11b81526001600160a01b0386811660048301528581166024830152604482018590529091169063dc1a06fa90606401600060405180830381600087803b158015614a4457600080fd5b505af1158015614a58573d6000803e3d6000fd5b505050508080614a679061596e565b9150506149c6565b6000614ac4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150e79092919063ffffffff16565b9050805160001480614ae5575080806020019051810190614ae59190615b4e565b6118ee5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d15565b6001600160a01b0381163b614bb15760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610d15565b600080516020615eb783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b614be9836150f6565b600082511180614bf65750805b156118ee576136ca8383615136565b6000826001600160a01b03167f05a71d417f891ba4b7a94b48d1b1f4b59b070921cba593b3c72a05a5587a78a9614c3b85612572565b60408051918252602082018690520160405180910390a2613cfb8383613d04565b6001600160a01b038116600090815261028f602052604090819020805464ffffffffff19164264ffffffffff161790555163038255fd60e11b81526102906004820152733F0Ff9947550d7Cf26549136552C785446ad4Ac590630704abfa906024016040805180830381865af4158015614cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cfe9190615cf2565b6001600160a01b038216600090815261028f602090815260408220835160018201559201516002909201805463ffffffff191663ffffffff909316929092179091555b6001600160a01b038216600090815261029260205260409020548110156119bf576001600160a01b0382166000908152610292602052604090208054614dac919083908110614d9257614d926158a9565b6000918252602090912001546001600160a01b0316614c5c565b80614db68161596e565b915050614d41565b6000614dc98261515b565b614dd39082615896565b905060005b6001600160a01b03831660009081526102926020526040902054811015614e61576001600160a01b0383166000908152610292602052604090208054614e43919083908110614e2957614e296158a9565b6000918252602090912001546001600160a01b0316614dbe565b614e4d9083615896565b915080614e598161596e565b915050614dd8565b50919050565b600080614e8061302661028e546001600160a01b031690565b90506000614e9e614e918888615d6f565b64ffffffffff1683614208565b90506000614eb06301e1338084614208565b614ebb600185614208565b614ec59084615acf565b614ecf91906158bf565b90506000614ee18761ffff16856141dc565b90506000614ef0600186614208565b614efa8385615acf565b614f0491906158bf565b90506000614f12888761419e565b90506000614f21606488614208565b614f2b8484615acf565b614f3591906158bf565b9050614f418188614236565b9750505050505050505b949350505050565b600054610100900460ff16614f7a5760405162461bcd60e51b8152600401610d1590615b03565b61153481615166565b600054610100900460ff16614faa5760405162461bcd60e51b8152600401610d1590615b03565b6135366151b0565b600054610100900460ff16614fd95760405162461bcd60e51b8152600401610d1590615b03565b61016080546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166150235760405162461bcd60e51b8152600401610d1590615b03565b61019380546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1661506d5760405162461bcd60e51b8152600401610d1590615b03565b609a6150798382615dda565b50609b6118ee8282615dda565b61508e61388c565b82615098816138d4565b156150b55760405162461bcd60e51b8152600401610d1590615a1f565b826150bf816138d4565b156150dc5760405162461bcd60e51b8152600401610d1590615a1f565b6120cd8585856151e3565b6060614f4b848460008561524b565b6150ff81614b44565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606110878383604051806060016040528060278152602001615ed760279139615326565b6000610ccf82612572565b600054610100900460ff1661518d5760405162461bcd60e51b8152600401610d1590615b03565b61012d80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166151d75760405162461bcd60e51b8152600401610d1590615b03565b60c9805460ff19169055565b6151eb611ab2565b156118ee5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610d15565b6060824710156152ac5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610d15565b600080866001600160a01b031685876040516152c89190615e9a565b60006040518083038185875af1925050503d8060008114615305576040519150601f19603f3d011682016040523d82523d6000602084013e61530a565b606091505b509150915061531b8783838761539e565b979650505050505050565b6060600080856001600160a01b0316856040516153439190615e9a565b600060405180830381855af49150503d806000811461537e576040519150601f19603f3d011682016040523d82523d6000602084013e615383565b606091505b50915091506153948683838761539e565b9695505050505050565b6060831561540d578251600003615406576001600160a01b0385163b6154065760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d15565b5081614f4b565b614f4b83838151156154225781518083602001fd5b8060405162461bcd60e51b8152600401610d159190615460565b60005b8381101561545757818101518382015260200161543f565b50506000910152565b602081526000825180602084015261547f81604085016020870161543c565b601f01601f19169190910160400192915050565b6001600160a01b038116811461153457600080fd5b600080604083850312156154bb57600080fd5b82356154c681615493565b946020939093013593505050565b6000602082840312156154e657600080fd5b813561108781615493565b600080600080600060a0868803121561550957600080fd5b853561551481615493565b9450602086013561552481615493565b9350604086013561553481615493565b9250606086013561554481615493565b9150608086013561555481615493565b809150509295509295909350565b60008060006060848603121561557757600080fd5b833561558281615493565b9250602084013561559281615493565b929592945050506040919091013590565b6000602082840312156155b557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156155f5576155f56155bc565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615624576156246155bc565b604052919050565b600067ffffffffffffffff821115615646576156466155bc565b50601f01601f191660200190565b6000806040838503121561566757600080fd5b823561567281615493565b9150602083013567ffffffffffffffff81111561568e57600080fd5b8301601f8101851361569f57600080fd5b80356156b26156ad8261562c565b6155fb565b8181528660208385010111156156c757600080fd5b816020840160208301376000602083830101528093505050509250929050565b61ffff8116811461153457600080fd5b60006020828403121561570957600080fd5b8135611087816156e7565b6000806040838503121561572757600080fd5b823561573281615493565b9150602083013561574281615493565b809150509250929050565b63ffffffff8116811461153457600080fd5b60006020828403121561577157600080fd5b81356110878161574d565b600181811c9082168061579057607f821691505b602082108103614e6157634e487b7160e01b600052602260045260246000fd5b6000602082840312156157c257600080fd5b815167ffffffffffffffff8111156157d957600080fd5b8201601f810184136157ea57600080fd5b80516157f86156ad8261562c565b81815285602083850101111561580d57600080fd5b61581e82602083016020860161543c565b95945050505050565b6702632b233b4ba3c960c51b81526000825161584a81600885016020870161543c565b9190910160080192915050565b601360fa1b81526000825161587381600185016020870161543c565b9190910160010192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610ccf57610ccf615880565b634e487b7160e01b600052603260045260246000fd5b6000826158dc57634e487b7160e01b600052601260045260246000fd5b500490565b600481106158ff57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160601b038581168252841660208201526080810161592860408301856158e1565b82606083015295945050505050565b81810381811115610ccf57610ccf615880565b6001600160601b0385168152602081018490526080810161592860408301856158e1565b60006001820161598057615980615880565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252600290820152614c3960f01b604082015260600190565b600060208284031215615a4d57600080fd5b5051919050565b848152602081018490526080810161592860408301856158e1565b634e487b7160e01b600052603160045260246000fd5b600060208284031215615a9757600080fd5b815161108781615493565b600081615ab157615ab1615880565b506000190190565b634e487b7160e01b600052600160045260246000fd5b8082028115828204841417610ccf57610ccf615880565b600060208284031215615af857600080fd5b8151611087816156e7565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615b6057600080fd5b8151801515811461108757600080fd5b600060208284031215615b8257600080fd5b815160ff8116811461108757600080fd5b600181815b80851115615bce578160001904821115615bb457615bb4615880565b80851615615bc157918102915b93841c9390800290615b98565b509250929050565b600082615be557506001610ccf565b81615bf257506000610ccf565b8160018114615c085760028114615c1257615c2e565b6001915050610ccf565b60ff841115615c2357615c23615880565b50506001821b610ccf565b5060208310610133831016604e8410600b8410161715615c51575081810a610ccf565b615c5b8383615b93565b8060001904821115615c6f57615c6f615880565b029392505050565b60006110878383615bd6565b8281526060810161108760208301848051825260209081015163ffffffff16910152565b600060408284031215615cb957600080fd5b615cc16155d2565b8251615ccc816156e7565b8152602083015164ffffffffff81168114615ce657600080fd5b60208201529392505050565b600060408284031215615d0457600080fd5b615d0c6155d2565b825181526020830151615ce68161574d565b8251815260208084015163ffffffff16908201526080810182516040830152602083015163ffffffff166060830152611087565b8151815260208083015163ffffffff169082015260408101610ccf565b64ffffffffff828116828216039080821115615d8d57615d8d615880565b5092915050565b601f8211156118ee57600081815260208120601f850160051c81016020861015615dbb5750805b601f850160051c820191505b8181101561100457828155600101615dc7565b815167ffffffffffffffff811115615df457615df46155bc565b615e0881615e02845461577c565b84615d94565b602080601f831160018114615e3d5760008415615e255750858301515b600019600386901b1c1916600185901b178555611004565b600085815260208120601f198616915b82811015615e6c57888601518255948401946001909101908401615e4d565b5085821015615e8a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251615eac81846020870161543c565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564d58e94604d90293a1c1ad95bfe6a6e6c352c33c5774a4b6b4f4b6f7460da29c5a2646970667358221220daaace9b8035ecd78de648f3491e9930a1c5193402b38b3f992525f9f0c881d564736f6c63430008120033", - "deployedBytecode": "0x6080604052600436106103d95760003560e01c80638980f11f116101fd578063c822adda11610118578063dd62ed3e116100ab578063ef356a791161007a578063ef356a7914610b96578063f12d54d814610bab578063f2fde38b14610bca578063f762e73414610bea578063f94ce2c214610c0957600080fd5b8063dd62ed3e14610b11578063ee1335d114610b31578063ee153c4f14610b51578063ef2591af14610b7157600080fd5b8063d038875c116100e7578063d038875c14610a8d578063d039981b14610ac7578063d294f09314610ae7578063db84faac14610afc57600080fd5b8063c822adda14610a05578063c89d5b8b14610a25578063cafb220214610a4d578063cdc1842414610a6c57600080fd5b8063a457c2d711610190578063b2de2a431161015f578063b2de2a431461097a578063b60d42881461098f578063b6b55f25146109b0578063bacd609e146109d057600080fd5b8063a457c2d7146108fa578063a64c91cc1461091a578063a8f763201461093a578063a9059cbb1461095a57600080fd5b806395d89b41116101cc57806395d89b411461089257806399a03c70146108a75780639c271975146108c75780639ee679e8146108e757600080fd5b80638980f11f146108065780638d8e6bd7146108265780638da5cb5b1461085d57806392e5ced71461087257600080fd5b80634134bee9116102f85780636d3a4ac81161028b578063734d82871161025a578063734d8287146107795780637594d0b51461079057806375a5652b146107a75780637c2edb16146107c75780638370e1f7146107e657600080fd5b80636d3a4ac8146107055780636f307dc31461072557806370a0823114610744578063715018a61461076457600080fd5b806353ac4b66116102c757806353ac4b661461067257806353d3a42f146106895780635c975abb146106d05780635f0e8e37146106e557600080fd5b80634134bee91461060a57806345b05d091461062a5780634f1ef2861461064a57806352d1902d1461065d57600080fd5b806323b872dd116103705780633659cfe61161033f5780633659cfe614610571578063391d85ec1461059157806339509351146105ca5780633e7ae353146105ea57600080fd5b806323b872dd146104f55780632a1b8b1c146105155780632f4f21e21461052a578063313ce5671461054a57600080fd5b80631459457a116103ac5780631459457a1461047b57806318160ddd1461049b5780631c19be6d146104be578063205c2878146104d557600080fd5b806306fdde03146103de578063095ea7b3146104095780630d174c24146104395780630e21750f1461045b575b600080fd5b3480156103ea57600080fd5b506103f3610c29565b6040516104009190615460565b60405180910390f35b34801561041557600080fd5b506104296104243660046154a8565b610cbb565b6040519015158152602001610400565b34801561044557600080fd5b506104596104543660046154d4565b610cd5565b005b34801561046757600080fd5b506104596104763660046154d4565b610d41565b34801561048757600080fd5b506104596104963660046154f1565b610da8565b3480156104a757600080fd5b506104b061100c565b604051908152602001610400565b3480156104ca57600080fd5b506104b06102fe5481565b3480156104e157600080fd5b506104296104f03660046154a8565b611037565b34801561050157600080fd5b50610429610510366004615562565b611068565b34801561052157600080fd5b5061045961108e565b34801561053657600080fd5b506104296105453660046154a8565b61141d565b34801561055657600080fd5b5061055f61144e565b60405160ff9091168152602001610400565b34801561057d57600080fd5b5061045961058c3660046154d4565b611458565b34801561059d57600080fd5b506102f9546105b2906001600160a01b031681565b6040516001600160a01b039091168152602001610400565b3480156105d657600080fd5b506104296105e53660046154a8565b611537565b3480156105f657600080fd5b506105b26106053660046154a8565b611559565b34801561061657600080fd5b506104596106253660046155a3565b611592565b34801561063657600080fd5b506104596106453660046155a3565b611786565b610459610658366004615654565b6118f3565b34801561066957600080fd5b506104b06119c3565b34801561067e57600080fd5b506104b06102fd5481565b34801561069557600080fd5b506106a96106a43660046155a3565b611a76565b604080516001600160a01b0390931683526001600160601b03909116602083015201610400565b3480156106dc57600080fd5b50610429611ab2565b3480156106f157600080fd5b506104596107003660046154d4565b611abc565b34801561071157600080fd5b506104596107203660046156f7565b611c13565b34801561073157600080fd5b506102c6546001600160a01b03166105b2565b34801561075057600080fd5b506104b061075f3660046154d4565b611cc4565b34801561077057600080fd5b50610459611ce2565b34801561078557600080fd5b506104b06102fc5481565b34801561079c57600080fd5b506104b06103005481565b3480156107b357600080fd5b506104596107c23660046155a3565b611d18565b3480156107d357600080fd5b50610193546001600160a01b03166105b2565b3480156107f257600080fd5b506104596108013660046155a3565b6120d4565b34801561081257600080fd5b506104596108213660046154a8565b612258565b34801561083257600080fd5b506105b26108413660046154d4565b610291602052600090815260409020546001600160a01b031681565b34801561086957600080fd5b506105b26122bd565b34801561087e57600080fd5b5061045961088d366004615714565b61232c565b34801561089e57600080fd5b506103f3612563565b3480156108b357600080fd5b506104b06108c23660046154d4565b612572565b3480156108d357600080fd5b506104596108e23660046154d4565b612590565b6104596108f53660046155a3565b6125eb565b34801561090657600080fd5b506104296109153660046154a8565b612952565b34801561092657600080fd5b506104596109353660046154d4565b6129d8565b34801561094657600080fd5b50610459610955366004615714565b612a03565b34801561096657600080fd5b506104296109753660046154a8565b612d39565b34801561098657600080fd5b50610459612d47565b34801561099b57600080fd5b506102fb546105b2906001600160a01b031681565b3480156109bc57600080fd5b506104596109cb3660046155a3565b612e30565b3480156109dc57600080fd5b506109f06109eb3660046154a8565b612f87565b60408051928352602083019190915201610400565b348015610a1157600080fd5b506106a9610a203660046155a3565b6130a3565b348015610a3157600080fd5b50610a3a6130b4565b60405161ffff9091168152602001610400565b348015610a5957600080fd5b5061028e546001600160a01b03166105b2565b348015610a7857600080fd5b506102fa546105b2906001600160a01b031681565b348015610a9957600080fd5b506102fb54610ab290600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610400565b348015610ad357600080fd5b506104b0610ae23660046154d4565b61312c565b348015610af357600080fd5b50610459613139565b348015610b0857600080fd5b506104b06131fa565b348015610b1d57600080fd5b506104b0610b2c366004615714565b613281565b348015610b3d57600080fd5b50610459610b4c36600461575f565b6132ac565b348015610b5d57600080fd5b506105b2610b6c3660046155a3565b6132db565b348015610b7d57600080fd5b506102fb54610ab290600160c01b900463ffffffff1681565b348015610ba257600080fd5b506104b0613306565b348015610bb757600080fd5b50610160546001600160a01b03166105b2565b348015610bd657600080fd5b50610459610be53660046154d4565b613311565b348015610bf657600080fd5b5061012d546001600160a01b03166105b2565b348015610c1557600080fd5b50610459610c2436600461575f565b613346565b6060609a8054610c389061577c565b80601f0160208091040260200160405190810160405280929190818152602001828054610c649061577c565b8015610cb15780601f10610c8657610100808354040283529160200191610cb1565b820191906000526020600020905b815481529060010190602001808311610c9457829003601f168201915b5050505050905090565b600033610cc98185856133b3565b60019150505b92915050565b610cdd6134d7565b6001600160a01b038116610d1e5760405162461bcd60e51b81526020600482015260036024820152624c363360e81b60448201526064015b60405180910390fd5b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055565b610d496134d7565b6001600160a01b038116610d855760405162461bcd60e51b8152602060048201526003602482015262130d8d60ea1b6044820152606401610d15565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1615808015610dc85750600054600160ff909116105b80610de25750303b158015610de2575060005460ff166001145b610e455760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610d15565b6000805460ff191660011790558015610e68576000805461ff0019166101001790555b6000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ea8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed091908101906157b0565b9050610f1d87878784604051602001610ee99190615827565b60405160208183030381529060405285604051602001610f099190615857565b604051602081830303815290604052613538565b610f268361357c565b610f2f306135ac565b6102f980546001600160a01b0319166001600160a01b0386161790556102fb805467ffffffffffffffff60a01b19166509c40000004b60a21b179055610f736122bd565b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055610f9c6122bd565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055508015611004576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b60006102fc546102fd5461101e613306565b6110289190615896565b6110329190615896565b905090565b60405162461bcd60e51b81526020600482015260036024820152624c343560e81b6044820152600090606401610d15565b600033611076858285613656565b6110818585856136d0565b60019150505b9392505050565b6102fa546001600160a01b0316336001600160a01b0316146110d85760405162461bcd60e51b81526020600482015260036024820152624c333960e81b6044820152606401610d15565b6110e061388c565b610300546102ff5460009182915b808210156113c05761afc85a106113c05760006102ff8381548110611115576111156158a9565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150156113ad578051611164906138d4565b156111e6576102ff838154811061117d5761117d6158a9565b60009182526020808320909101829055610301805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177fe78f8e39db67a8c6e0d54c288efc6f296f5d558bc028138a8476c9b97f6fcaa4909101556113ad565b60026111f06131fa565b6111fa91906158bf565b81602001516001600160601b031611156112c65760208101516102ff5460405160019233928792600080516020615efe833981519152926112419290918291600391615903565b60405180910390a46102ff838154811061125d5761125d6158a9565b600091825260208083209091018290556102ff805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec909101556113ad565b6000806112e4836000015184602001516001600160601b0316612f87565b91509150856102fe546112f79190615937565b821115611306575050506113c0565b6113108188615896565b965061131c8287615896565b9550600183600001516001600160a01b031686600080516020615efe8339815191528660200151866002600019604051611359949392919061594a565b60405180910390a46102ff8581548110611375576113756158a9565b600091825260208220015582516113aa908361139a6102c6546001600160a01b031690565b6001600160a01b03169190613944565b50505b826113b78161596e565b935050506110ee565b836102fc60008282546113d39190615896565b92505081905550826102fe60008282546113ed9190615937565b909155506113fd90508484615896565b6102fd600082825461140f9190615937565b909155505050610300555050565b60405162461bcd60e51b8152602060048201526003602482015262261a1b60e91b6044820152600090606401610d15565b60006110326139a7565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036114a05760405162461bcd60e51b8152600401610d1590615987565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166114e9600080516020615eb7833981519152546001600160a01b031690565b6001600160a01b03161461150f5760405162461bcd60e51b8152600401610d15906159d3565b61151881613a1d565b6040805160008082526020820190925261153491839190613a25565b50565b600033610cc981858561154a8383613281565b6115549190615896565b6133b3565b610292602052816000526040600020818154811061157657600080fd5b6000918252602090912001546001600160a01b03169150829050565b61159a61388c565b336115a4816138d4565b156115c15760405162461bcd60e51b8152600401610d1590615a1f565b6115ca33611cc4565b8211156115ff5760405162461bcd60e51b815260206004820152600360248201526209868760eb1b6044820152606401610d15565b60006102fe54836102fd546116149190615896565b6102f95491101591506000906002906001600160a01b031663c8f74bb8336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169a9190615a3b565b101580156116ab57506102fe548411155b905081806116b65750805b6116e85760405162461bcd60e51b81526020600482015260036024820152624c343960e81b6044820152606401610d15565b6000806116f53387612f87565b91509150806102fc600082825461170c9190615896565b92505081905550816102fe60008282546117269190615937565b9091555060019050336001600160a01b0316600019600080516020615efe833981519152898660026000196040516117619493929190615a54565b60405180910390a46117733382613b90565b61177d3383613cd7565b50505050505050565b61178e61388c565b33611798816138d4565b156117b55760405162461bcd60e51b8152600401610d1590615a1f565b60006102ff83815481106117cb576117cb6158a9565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150336001600160a01b0316146118475760405162461bcd60e51b81526020600482015260036024820152624c353760e81b6044820152606401610d15565b80602001516001600160601b03166102fd60008282546118679190615937565b90915550506102ff805484908110611881576118816158a9565b6000918252602082200155600181600001516001600160a01b031684600080516020615efe8339815191528460200151856020015160016000196040516118cb9493929190615903565b60405180910390a46118ee816000015182602001516001600160601b0316613d04565b505050565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361193b5760405162461bcd60e51b8152600401610d1590615987565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611984600080516020615eb7833981519152546001600160a01b031690565b6001600160a01b0316146119aa5760405162461bcd60e51b8152600401610d15906159d3565b6119b382613a1d565b6119bf82826001613a25565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a635760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610d15565b50600080516020615eb783398151915290565b6103018181548110611a8757600080fd5b6000918252602090912001546001600160a01b0381169150600160a01b90046001600160601b031682565b6000611032613dd9565b611ac46134d7565b610302546000199060005b81811015611b2957836001600160a01b03166103028281548110611af557611af56158a9565b6000918252602090912001546001600160a01b031603611b1757809250611b29565b80611b218161596e565b915050611acf565b506000198213611b615760405162461bcd60e51b8152602060048201526003602482015262261a1960e91b6044820152606401610d15565b610302611b6f600183615937565b81548110611b7f57611b7f6158a9565b60009182526020909120015461030280546001600160a01b039092169184908110611bac57611bac6158a9565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550610302805480611bec57611bec615a6f565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b611c1b6134d7565b60405163433e3bad60e11b8152610290600482015261ffff8216602482015273__$3728f51d90da6977d2525dcec632daa0b3$__9063867c775a9060440160006040518083038186803b158015611c7157600080fd5b505af4158015611c85573d6000803e3d6000fd5b505060405161ffff841681527f3d6d63f501ae621a01c729938fb4428a25138835257943d6b56c49b402ba36329250602001905060405180910390a150565b6000611ccf8261312c565b611cd883612572565b610ccf9190615896565b611cea6134d7565b60405162461bcd60e51b81526020600482015260036024820152624c363560e81b6044820152606401610d15565b6102fb546001600160a01b0316336001600160a01b031614611d625760405162461bcd60e51b815260206004820152600360248201526204c34360ec1b6044820152606401610d15565b611d6a61388c565b60006102ff8281548110611d8057611d806158a9565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150611df15760405162461bcd60e51b8152602060048201526003602482015262261b1b60e91b6044820152606401610d15565b8051611dfc906138d4565b15611e2f5760405162461bcd60e51b815260206004820152600360248201526204c35360ec1b6044820152606401610d15565b6002611e396131fa565b611e4391906158bf565b81602001516001600160601b031611611e845760405162461bcd60e51b81526020600482015260036024820152624c353160e81b6044820152606401610d15565b600080611ea2836000015184602001516001600160601b0316612f87565b915091506000611ebb6102c6546001600160a01b031690565b6102fb546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa158015611f05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f299190615a3b565b9050806102fe54611f3a9190615896565b831115611f6f5760405162461bcd60e51b8152602060048201526003602482015262261a9960e91b6044820152606401610d15565b816102fc6000828254611f829190615896565b9250508190555083602001516001600160601b03166102fd6000828254611fa99190615937565b9091555050610300548503611fcf576103008054906000611fc98361596e565b91905055505b600184600001516001600160a01b031686600080516020615efe833981519152876020015187600260001960405161200a949392919061594a565b60405180910390a46102ff8581548110612026576120266158a9565b600091825260208220015580831161206857612063338551856120526102c6546001600160a01b031690565b6001600160a01b0316929190613e48565b6120c5565b60006120748285615937565b9050806102fe60008282546120899190615937565b909155506120a99050338651846120526102c6546001600160a01b031690565b84516120c3908261139a6102c6546001600160a01b031690565b505b6120cd613e80565b5050505050565b6102fb546001600160a01b0316336001600160a01b03161461211e5760405162461bcd60e51b815260206004820152600360248201526204c34360ec1b6044820152606401610d15565b61212661388c565b6102c6546001600160a01b03166102fb546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa15801561217d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a19190615a3b565b8111156121d65760405162461bcd60e51b81526020600482015260036024820152620986a760eb1b6044820152606401610d15565b6000816102fe546121e79190615896565b90506121f16131fa565b8111156122265760405162461bcd60e51b81526020600482015260036024820152624c353960e81b6044820152606401610d15565b816102fe60008282546122399190615896565b909155506119bf90503330846120526102c6546001600160a01b031690565b6122606134d7565b6102c6546001600160a01b03166001600160a01b0316826001600160a01b0316036122b35760405162461bcd60e51b81526020600482015260036024820152624c343360e81b6044820152606401610d15565b6119bf8282613ee9565b61012d5460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015612308573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615a85565b61233461388c565b8161233e816138d4565b1561235b5760405162461bcd60e51b8152600401610d1590615a1f565b81612365816138d4565b156123825760405162461bcd60e51b8152600401610d1590615a1f565b6001600160a01b038481166000908152610291602052604090205416156123d15760405162461bcd60e51b8152602060048201526003602482015262261b1960e91b6044820152606401610d15565b6001600160a01b03841661240d5760405162461bcd60e51b815260206004820152600360248201526226189960e91b6044820152606401610d15565b6001600160a01b0383166124495760405162461bcd60e51b81526020600482015260036024820152624c313360e81b6044820152606401610d15565b826001600160a01b0316846001600160a01b0316036124905760405162461bcd60e51b8152602060048201526003602482015262130c4d60ea1b6044820152606401610d15565b6124986122bd565b6001600160a01b0316336001600160a01b031614806124bf5750336001600160a01b038516145b6124f15760405162461bcd60e51b81526020600482015260036024820152624c313560e81b6044820152606401610d15565b6124fc846001613fdb565b612507836001613fdb565b50506001600160a01b039182166000818152610291602090815260408083208054969095166001600160a01b03199687168117909555938252610292815292812080546001810182559082529290209091018054909216179055565b6060609b8054610c389061577c565b6001600160a01b038116600090815260976020526040812054610ccf565b6125986134d7565b61030280546001810182556000919091527f552430c2010355dda19e8bae437f75cfb136cb8d667c4c0867367db21eee69b60180546001600160a01b0319166001600160a01b0392909216919091179055565b6125f361388c565b336125fd816138d4565b1561261a5760405162461bcd60e51b8152600401610d1590615a1f565b61262333611cc4565b8211156126585760405162461bcd60e51b81526020600482015260036024820152624c353360e81b6044820152606401610d15565b6001600160601b038211156126955760405162461bcd60e51b8152602060048201526003602482015262130d4d60ea1b6044820152606401610d15565b34660aa87bee538000146126d15760405162461bcd60e51b81526020600482015260036024820152624c353560e81b6044820152606401610d15565b600060405180604001604052806126e53390565b6001600160a01b0390811682526001600160601b0386166020909201919091526102f9549192506000916002911663c8f74bb8336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561275d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127819190615a3b565b101580156127925750600061030054115b156128005761030080549060006127a883615aa2565b9190505550610300549050816102ff82815481106127c8576127c86158a9565b6000918252602091829020835193909201516001600160601b0316600160a01b026001600160a01b039093169290921791015561286a565b6102ff8054600181810183556000839052845160208601516001600160601b0316600160a01b026001600160a01b03909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec9092019190915590546128679190615937565b90505b836102fd600082825461287d9190615896565b9091555060019050336001600160a01b031682600080516020615efe833981519152878860006000196040516128b69493929190615a54565b60405180910390a46128c83385613b90565b6102fa546040516000916001600160a01b03169034908381818185875af1925050503d8060008114612916576040519150601f19603f3d011682016040523d82523d6000602084013e61291b565b606091505b50509050806120cd5760405162461bcd60e51b8152602060048201526003602482015262261a9b60e91b6044820152606401610d15565b600033816129608286613281565b9050838110156129c05760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610d15565b6129cd82868684036133b3565b506001949350505050565b6129e06134d7565b6102f980546001600160a01b0319166001600160a01b0392909216919091179055565b612a0b61388c565b81612a15816138d4565b15612a325760405162461bcd60e51b8152600401610d1590615a1f565b81612a3c816138d4565b15612a595760405162461bcd60e51b8152600401610d1590615a1f565b6001600160a01b038416612a955760405162461bcd60e51b815260206004820152600360248201526226189b60e91b6044820152606401610d15565b6001600160a01b038316612ad15760405162461bcd60e51b81526020600482015260036024820152624c313760e81b6044820152606401610d15565b612ad96122bd565b6001600160a01b0316336001600160a01b03161480612b005750336001600160a01b038516145b612b325760405162461bcd60e51b815260206004820152600360248201526209862760eb1b6044820152606401610d15565b6001600160a01b0384811660009081526102916020526040902054811690841614612b855760405162461bcd60e51b81526020600482015260036024820152624c313960e81b6044820152606401610d15565b612b90846001613fdb565b612b9b836001613fdb565b60001960005b6001600160a01b03851660009081526102926020526040902054811015612c26576001600160a01b0385811660009081526102926020526040902080549188169183908110612bf257612bf26158a9565b6000918252602090912001546001600160a01b031603612c1457809150612c26565b80612c1e8161596e565b915050612ba1565b506000811215612c3857612c38615ab9565b6001600160a01b0380861660009081526102916020908152604080832080546001600160a01b031916905592871682526102929052208054612c7c90600190615937565b81548110612c8c57612c8c6158a9565b60009182526020808320909101546001600160a01b0387811684526102929092526040909220805491909216919083908110612cca57612cca6158a9565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918616815261029290915260409020805480612d1057612d10615a6f565b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b600033610cc98185856136d0565b612d4f6134d7565b60006102fe54612d686102c6546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015612dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd29190615a3b565b612ddc9190615937565b905060008111612e145760405162461bcd60e51b8152602060048201526003602482015262130d0d60ea1b6044820152606401610d15565b611534612e2a6102c6546001600160a01b031690565b82613ee9565b612e3861388c565b33612e42816138d4565b15612e5f5760405162461bcd60e51b8152600401610d1590615a1f565b81612e736102c6546001600160a01b031690565b6001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eea9190615a3b565b1015612f1e5760405162461bcd60e51b81526020600482015260036024820152624c343760e81b6044820152606401610d15565b816102fe6000828254612f319190615896565b9091555060009050336001600160a01b0316600019600080516020615efe83398151915285866002600019604051612f6c9493929190615a54565b60405180910390a4612f7e33836140b0565b506119bf613e80565b6102f95460405163191ee97760e31b81526001600160a01b03848116600483015260009283926002929091169063c8f74bb890602401602060405180830381865afa158015612fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffe9190615a3b565b1061300e5750819050600061309c565b600061302b61302661028e546001600160a01b031690565b614131565b90506000613039858361419e565b6102fb5490915060009061305a90600160a01b900463ffffffff16846141dc565b90506000613069606485614208565b6130738385615acf565b61307d91906158bf565b90506130898185614236565b94506130958588615937565b9550505050505b9250929050565b6102ff8181548110611a8757600080fd5b60405163106d64cf60e31b8152610290600482015260009073__$3728f51d90da6977d2525dcec632daa0b3$__9063836b267890602401602060405180830381865af4158015613108573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615ae6565b6000610ccf82600161426d565b6131416134d7565b60006102fc541161317a5760405162461bcd60e51b815260206004820152600360248201526204c36360ec1b6044820152606401610d15565b6102fc546102fe5410156131b65760405162461bcd60e51b81526020600482015260036024820152624c363160e81b6044820152606401610d15565b6102fc546102fe60008282546131cc9190615937565b90915550506102fc805460009091556115346131e66122bd565b8261139a6102c6546001600160a01b031690565b60008061321361302661028e546001600160a01b031690565b9050600061322861322261100c565b8361419e565b6102fb5490915060009061324990600160c01b900463ffffffff16846141dc565b90506000613258606485614208565b6132628385615acf565b61326c91906158bf565b90506132788185614236565b94505050505090565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6132b46134d7565b6102fb805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b61030281815481106132ec57600080fd5b6000918252602090912001546001600160a01b0316905081565b600061103260995490565b6133196134d7565b60405162461bcd60e51b8152602060048201526002602482015261098760f31b6044820152606401610d15565b61334e6134d7565b61271063ffffffff8216111561338c5760405162461bcd60e51b81526020600482015260036024820152624c343160e81b6044820152606401610d15565b6102fb805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b6001600160a01b0383166134155760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610d15565b6001600160a01b0382166134765760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610d15565b6001600160a01b0383811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b336134e06122bd565b6001600160a01b0316146135365760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d15565b565b600054610100900460ff1661355f5760405162461bcd60e51b8152600401610d1590615b03565b61356a8585856147d3565b613574828261482d565b6120cd61485e565b600054610100900460ff166135a35760405162461bcd60e51b8152600401610d1590615b03565b61153481614885565b600054610100900460ff166135d35760405162461bcd60e51b8152600401610d1590615b03565b61028e80546001600160a01b0319166001600160a01b03831617905560405163433e3bad60e11b815261029060048201526000602482015273__$3728f51d90da6977d2525dcec632daa0b3$__9063867c775a9060440160006040518083038186803b15801561364257600080fd5b505af41580156120cd573d6000803e3d6000fd5b60006136628484613281565b905060001981146136ca57818110156136bd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610d15565b6136ca84848484036133b3565b50505050565b6001600160a01b0383166137345760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610d15565b6001600160a01b0382166137965760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610d15565b6137a1838383614927565b6001600160a01b038316600090815260976020526040902054818110156138195760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610d15565b6001600160a01b0380851660008181526097602052604080822086860390559286168082529083902080548601905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906138799086815260200190565b60405180910390a36136ca848484614966565b613894611ab2565b156135365760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610d15565b6101935460405163fe575a8760e01b81526001600160a01b038381166004830152600092169063fe575a8790602401602060405180830381865afa158015613920573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccf9190615b4e565b6040516001600160a01b0383166024820152604481018290526118ee90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614a6f565b6102c6546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048083019260209291908290030181865afa925050508015613a0e575060408051601f3d908101601f19168201909252613a0b91810190615b70565b60015b613a185750601290565b919050565b6115346134d7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615613a58576118ee83614b44565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613ab2575060408051601f3d908101601f19168201909252613aaf91810190615a3b565b60015b613b155760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610d15565b600080516020615eb78339815191528114613b845760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610d15565b506118ee838383614be0565b6001600160a01b038216613bf05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610d15565b613bfc82600083614927565b6001600160a01b03821660009081526097602052604090205481811015613c705760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610d15565b6001600160a01b03831660008181526097602090815260408083208686039055609980548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36118ee83600084614966565b6000613ce33383613b90565b6102c654613cfb906001600160a01b03168484613944565b50600192915050565b6001600160a01b038216613d5a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610d15565b613d6660008383614927565b8060996000828254613d789190615896565b90915550506001600160a01b0382166000818152609760209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36119bf60008383614966565b6101605460408051635c975abb60e01b815290516000926001600160a01b031691635c975abb9160048083019260209291908290030181865afa158015613e24573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110329190615b4e565b6040516001600160a01b03808516602483015283166044820152606481018290526136ca9085906323b872dd60e01b90608401613970565b6000613e8a6131fa565b9050806102fe5411613e995750565b6000816102fe54613eaa9190615937565b9050806102fe6000828254613ebf9190615937565b90915550506102fb546119bf906001600160a01b03168261139a6102c6546001600160a01b031690565b613ef16134d7565b60008111613f275760405162461bcd60e51b815260206004820152600360248201526204c31360ec1b6044820152606401610d15565b6040516370a0823160e01b8152306004820152829082906001600160a01b038316906370a0823190602401602060405180830381865afa158015613f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f939190615a3b565b1015613fc75760405162461bcd60e51b81526020600482015260036024820152624c313160e81b6044820152606401610d15565b6118ee6001600160a01b0382163384613944565b6102935460ff1615613feb575050565b6001600160a01b038216600090815261028f602052604090205464ffffffffff428116911603614019575050565b6001600160a01b0380831660009081526102916020526040902054168015614045576118ee8183613fdb565b6000614051848461426d565b905080156140a757610293805460ff1916600117905560006140738583614c05565b610293805460ff191690559050806140a5576001600160a01b038516600090815261028f602052604090206003018290555b505b6136ca84614c5c565b60003330810361410e5760405162461bcd60e51b815260206004820152602360248201527f4552433230577261707065723a20777261707065722063616e2774206465706f6044820152621cda5d60ea1b6064820152608401610d15565b6102c654614127906001600160a01b0316823086613e48565b610cc98484613d04565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015614171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141959190615b70565b60ff1692915050565b600060038210156141d0576141b4826006615937565b6141bf90600a615c77565b6141c99084615acf565b9050610ccf565b611087836103e8615acf565b600060038210156141f3576141c9836103e8615acf565b6141fe82600a615c77565b6110879084615acf565b60006003821015614220576141c983620f4240615acf565b61422b826003615896565b6141fe90600a615c77565b600060038210156142615761424c826006615937565b61425790600a615c77565b6141c990846158bf565b6110876103e8846158bf565b6001600160a01b038216600090815261028f602090815260408083208151608081018352815464ffffffffff16818401908152835180850190945260018301548452600283015463ffffffff168486015260608201939093529182526003015491810191909152816142de85614dbe565b82515190915064ffffffffff1615806142f5575080155b1561430557600092505050610ccf565b815160200151604051630b27cfb160e31b815260009073__$3728f51d90da6977d2525dcec632daa0b3$__9063593e7d889061434990610290908690600401615c83565b6040805180830381865af4158015614365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143899190615ca7565b60405163038255fd60e11b8152610290600482015290915060009073__$3728f51d90da6977d2525dcec632daa0b3$__90630704abfa906024016040805180830381865af41580156143df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144039190615cf2565b90508460200151955073__$3728f51d90da6977d2525dcec632daa0b3$__634ead0c5384836040518363ffffffff1660e01b8152600401614445929190615d1e565b602060405180830381865af4158015614462573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144869190615b4e565b61479757604051633e1e5c5360e11b815260009073__$3728f51d90da6977d2525dcec632daa0b3$__90637c3cb8a6906144c4908790600401615d52565b6040805180830381865af41580156144e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145049190615cf2565b604051630b27cfb160e31b815290915060009073__$3728f51d90da6977d2525dcec632daa0b3$__9063593e7d889061454590610290908690600401615c83565b6040805180830381865af4158015614561573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145859190615ca7565b875151602082015186519293506145b3928c6145a25760006145a4565b8b5b6145ae908b615896565b614e67565b6145bd9089615896565b97505b81945080935073__$3728f51d90da6977d2525dcec632daa0b3$__634ead0c5386856040518363ffffffff1660e01b81526004016145ff929190615d1e565b602060405180830381865af415801561461c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146409190615b4e565b61476a57604051633e1e5c5360e11b815273__$3728f51d90da6977d2525dcec632daa0b3$__90637c3cb8a69061467b908890600401615d52565b6040805180830381865af4158015614697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146bb9190615cf2565b604051630b27cfb160e31b815290925073__$3728f51d90da6977d2525dcec632daa0b3$__9063593e7d88906146f990610290908690600401615c83565b6040805180830381865af4158015614715573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147399190615ca7565b90506147598460200151826020015186600001518c6145a25760006145a4565b6147639089615896565b97506145c0565b61478484602001514286600001518c6145a25760006145a4565b61478e9089615896565b975050506147c8565b84515182516147bb919042908a6147af5760006147b1565b895b6145ae9089615896565b6147c59087615896565b95505b505050505092915050565b600054610100900460ff166147fa5760405162461bcd60e51b8152600401610d1590615b03565b61480261485e565b61480b83614f53565b614813614f83565b61481c82614fb2565b61482581614ffc565b6118ee61485e565b600054610100900460ff166148545760405162461bcd60e51b8152600401610d1590615b03565b6119bf8282615046565b600054610100900460ff166135365760405162461bcd60e51b8152600401610d1590615b03565b600054610100900460ff166148ac5760405162461bcd60e51b8152600401610d1590615b03565b306001600160a01b038216036149045760405162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a2063616e6e6f742073656c66207772617000006044820152606401610d15565b6102c680546001600160a01b0319166001600160a01b0392909216919091179055565b614932838383615086565b6001600160a01b0383161561494c5761494c836001613fdb565b6001600160a01b038216156118ee576118ee826001613fdb565b6001600160a01b038316158061498357506001600160a01b038216155b156149c3577f980f7e6fb44009001d533a10bc3bd558b4efe22dcb4888bca4767aa93c71ce1f6149b161100c565b60405190815260200160405180910390a15b60005b610302548110156136ca5761030281815481106149e5576149e56158a9565b600091825260209091200154604051636e0d037d60e11b81526001600160a01b0386811660048301528581166024830152604482018590529091169063dc1a06fa90606401600060405180830381600087803b158015614a4457600080fd5b505af1158015614a58573d6000803e3d6000fd5b505050508080614a679061596e565b9150506149c6565b6000614ac4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166150e79092919063ffffffff16565b9050805160001480614ae5575080806020019051810190614ae59190615b4e565b6118ee5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d15565b6001600160a01b0381163b614bb15760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610d15565b600080516020615eb783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b614be9836150f6565b600082511180614bf65750805b156118ee576136ca8383615136565b6000826001600160a01b03167f05a71d417f891ba4b7a94b48d1b1f4b59b070921cba593b3c72a05a5587a78a9614c3b85612572565b60408051918252602082018690520160405180910390a2613cfb8383613d04565b6001600160a01b038116600090815261028f602052604090819020805464ffffffffff19164264ffffffffff161790555163038255fd60e11b8152610290600482015273__$3728f51d90da6977d2525dcec632daa0b3$__90630704abfa906024016040805180830381865af4158015614cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cfe9190615cf2565b6001600160a01b038216600090815261028f602090815260408220835160018201559201516002909201805463ffffffff191663ffffffff909316929092179091555b6001600160a01b038216600090815261029260205260409020548110156119bf576001600160a01b0382166000908152610292602052604090208054614dac919083908110614d9257614d926158a9565b6000918252602090912001546001600160a01b0316614c5c565b80614db68161596e565b915050614d41565b6000614dc98261515b565b614dd39082615896565b905060005b6001600160a01b03831660009081526102926020526040902054811015614e61576001600160a01b0383166000908152610292602052604090208054614e43919083908110614e2957614e296158a9565b6000918252602090912001546001600160a01b0316614dbe565b614e4d9083615896565b915080614e598161596e565b915050614dd8565b50919050565b600080614e8061302661028e546001600160a01b031690565b90506000614e9e614e918888615d6f565b64ffffffffff1683614208565b90506000614eb06301e1338084614208565b614ebb600185614208565b614ec59084615acf565b614ecf91906158bf565b90506000614ee18761ffff16856141dc565b90506000614ef0600186614208565b614efa8385615acf565b614f0491906158bf565b90506000614f12888761419e565b90506000614f21606488614208565b614f2b8484615acf565b614f3591906158bf565b9050614f418188614236565b9750505050505050505b949350505050565b600054610100900460ff16614f7a5760405162461bcd60e51b8152600401610d1590615b03565b61153481615166565b600054610100900460ff16614faa5760405162461bcd60e51b8152600401610d1590615b03565b6135366151b0565b600054610100900460ff16614fd95760405162461bcd60e51b8152600401610d1590615b03565b61016080546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166150235760405162461bcd60e51b8152600401610d1590615b03565b61019380546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1661506d5760405162461bcd60e51b8152600401610d1590615b03565b609a6150798382615dda565b50609b6118ee8282615dda565b61508e61388c565b82615098816138d4565b156150b55760405162461bcd60e51b8152600401610d1590615a1f565b826150bf816138d4565b156150dc5760405162461bcd60e51b8152600401610d1590615a1f565b6120cd8585856151e3565b6060614f4b848460008561524b565b6150ff81614b44565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606110878383604051806060016040528060278152602001615ed760279139615326565b6000610ccf82612572565b600054610100900460ff1661518d5760405162461bcd60e51b8152600401610d1590615b03565b61012d80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166151d75760405162461bcd60e51b8152600401610d1590615b03565b60c9805460ff19169055565b6151eb611ab2565b156118ee5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610d15565b6060824710156152ac5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610d15565b600080866001600160a01b031685876040516152c89190615e9a565b60006040518083038185875af1925050503d8060008114615305576040519150601f19603f3d011682016040523d82523d6000602084013e61530a565b606091505b509150915061531b8783838761539e565b979650505050505050565b6060600080856001600160a01b0316856040516153439190615e9a565b600060405180830381855af49150503d806000811461537e576040519150601f19603f3d011682016040523d82523d6000602084013e615383565b606091505b50915091506153948683838761539e565b9695505050505050565b6060831561540d578251600003615406576001600160a01b0385163b6154065760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d15565b5081614f4b565b614f4b83838151156154225781518083602001fd5b8060405162461bcd60e51b8152600401610d159190615460565b60005b8381101561545757818101518382015260200161543f565b50506000910152565b602081526000825180602084015261547f81604085016020870161543c565b601f01601f19169190910160400192915050565b6001600160a01b038116811461153457600080fd5b600080604083850312156154bb57600080fd5b82356154c681615493565b946020939093013593505050565b6000602082840312156154e657600080fd5b813561108781615493565b600080600080600060a0868803121561550957600080fd5b853561551481615493565b9450602086013561552481615493565b9350604086013561553481615493565b9250606086013561554481615493565b9150608086013561555481615493565b809150509295509295909350565b60008060006060848603121561557757600080fd5b833561558281615493565b9250602084013561559281615493565b929592945050506040919091013590565b6000602082840312156155b557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156155f5576155f56155bc565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715615624576156246155bc565b604052919050565b600067ffffffffffffffff821115615646576156466155bc565b50601f01601f191660200190565b6000806040838503121561566757600080fd5b823561567281615493565b9150602083013567ffffffffffffffff81111561568e57600080fd5b8301601f8101851361569f57600080fd5b80356156b26156ad8261562c565b6155fb565b8181528660208385010111156156c757600080fd5b816020840160208301376000602083830101528093505050509250929050565b61ffff8116811461153457600080fd5b60006020828403121561570957600080fd5b8135611087816156e7565b6000806040838503121561572757600080fd5b823561573281615493565b9150602083013561574281615493565b809150509250929050565b63ffffffff8116811461153457600080fd5b60006020828403121561577157600080fd5b81356110878161574d565b600181811c9082168061579057607f821691505b602082108103614e6157634e487b7160e01b600052602260045260246000fd5b6000602082840312156157c257600080fd5b815167ffffffffffffffff8111156157d957600080fd5b8201601f810184136157ea57600080fd5b80516157f86156ad8261562c565b81815285602083850101111561580d57600080fd5b61581e82602083016020860161543c565b95945050505050565b6702632b233b4ba3c960c51b81526000825161584a81600885016020870161543c565b9190910160080192915050565b601360fa1b81526000825161587381600185016020870161543c565b9190910160010192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610ccf57610ccf615880565b634e487b7160e01b600052603260045260246000fd5b6000826158dc57634e487b7160e01b600052601260045260246000fd5b500490565b600481106158ff57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160601b038581168252841660208201526080810161592860408301856158e1565b82606083015295945050505050565b81810381811115610ccf57610ccf615880565b6001600160601b0385168152602081018490526080810161592860408301856158e1565b60006001820161598057615980615880565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252600290820152614c3960f01b604082015260600190565b600060208284031215615a4d57600080fd5b5051919050565b848152602081018490526080810161592860408301856158e1565b634e487b7160e01b600052603160045260246000fd5b600060208284031215615a9757600080fd5b815161108781615493565b600081615ab157615ab1615880565b506000190190565b634e487b7160e01b600052600160045260246000fd5b8082028115828204841417610ccf57610ccf615880565b600060208284031215615af857600080fd5b8151611087816156e7565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615b6057600080fd5b8151801515811461108757600080fd5b600060208284031215615b8257600080fd5b815160ff8116811461108757600080fd5b600181815b80851115615bce578160001904821115615bb457615bb4615880565b80851615615bc157918102915b93841c9390800290615b98565b509250929050565b600082615be557506001610ccf565b81615bf257506000610ccf565b8160018114615c085760028114615c1257615c2e565b6001915050610ccf565b60ff841115615c2357615c23615880565b50506001821b610ccf565b5060208310610133831016604e8410600b8410161715615c51575081810a610ccf565b615c5b8383615b93565b8060001904821115615c6f57615c6f615880565b029392505050565b60006110878383615bd6565b8281526060810161108760208301848051825260209081015163ffffffff16910152565b600060408284031215615cb957600080fd5b615cc16155d2565b8251615ccc816156e7565b8152602083015164ffffffffff81168114615ce657600080fd5b60208201529392505050565b600060408284031215615d0457600080fd5b615d0c6155d2565b825181526020830151615ce68161574d565b8251815260208084015163ffffffff16908201526080810182516040830152602083015163ffffffff166060830152611087565b8151815260208083015163ffffffff169082015260408101610ccf565b64ffffffffff828116828216039080821115615d8d57615d8d615880565b5092915050565b601f8211156118ee57600081815260208120601f850160051c81016020861015615dbb5750805b601f850160051c820191505b8181101561100457828155600101615dc7565b815167ffffffffffffffff811115615df457615df46155bc565b615e0881615e02845461577c565b84615d94565b602080601f831160018114615e3d5760008415615e255750858301515b600019600386901b1c1916600185901b178555611004565b600085815260208120601f198616915b82811015615e6c57888601518255948401946001909101908401615e4d565b5085821015615e8a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251615eac81846020870161543c565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564d58e94604d90293a1c1ad95bfe6a6e6c352c33c5774a4b6b4f4b6f7460da29c5a2646970667358221220daaace9b8035ecd78de648f3491e9930a1c5193402b38b3f992525f9f0c881d564736f6c63430008120033", + "solcInputHash": "763174e07eec40e5a74770adce214c49", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newAPRUD7x3\",\"type\":\"uint16\"}],\"name\":\"APRChangeEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int256\",\"name\":\"id\",\"type\":\"int256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum LToken.Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountAfterFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum LToken.Status\",\"name\":\"newStatus\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"newId\",\"type\":\"int256\"}],\"name\":\"ActivityEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"balanceBefore\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewards\",\"type\":\"uint256\"}],\"name\":\"MintedRewardsEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTVL\",\"type\":\"uint256\"}],\"name\":\"TVLChangeEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"cancelWithdrawalRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositFor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feesRateUD7x3\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"frozenRequests\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fund\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAPR\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpectedRetained\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"getWithdrawnAmountAndFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawnAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalBlacklist\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalPause\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"globalOwner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"globalPause_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"globalBlacklist_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ldyStaking_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingToken\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"instantWithdrawal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"invested\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ldyStaking\",\"outputs\":[{\"internalType\":\"contract LDYStaking\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"listenerContract\",\"type\":\"address\"}],\"name\":\"listenToTransfers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"processBigQueuedRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"processQueuedRequests\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"realBalanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"realTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"recoverERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"recoverUnderlying\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repatriate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"requestWithdrawal\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"retentionRateUD7x3\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardsRedirectsFromTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rewardsRedirectsToFrom\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"aprUD7x3\",\"type\":\"uint16\"}],\"name\":\"setAPR\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"feesRateUD7x3_\",\"type\":\"uint32\"}],\"name\":\"setFeesRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"fund_\",\"type\":\"address\"}],\"name\":\"setFund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"ldyStakingAddress\",\"type\":\"address\"}],\"name\":\"setLDYStaking\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"retentionRateUD7x3_\",\"type\":\"uint32\"}],\"name\":\"setRetentionRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawer_\",\"type\":\"address\"}],\"name\":\"setWithdrawer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrwalFeeInEth_\",\"type\":\"uint256\"}],\"name\":\"setWithdrwalFeeInEth\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"startRewardsRedirection\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"stopRewardsRedirection\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalQueued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfersListeners\",\"outputs\":[{\"internalType\":\"contract ITransfersListener\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unclaimedFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"underlying\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"listenerContract\",\"type\":\"address\"}],\"name\":\"unlistenToTransfers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"unmintedRewardsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usableUnderlyings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdrawalQueue\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawalQueueCursor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawer\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrwalFeeInEth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Lila Rest (https://lila.rest)\",\"custom:oz-upgrades-unsafe-allow\":\"external-library-linking\",\"custom:security-contact\":\"security@ledgity.comsecurity@ledgity.com\",\"details\":\"Definitions: - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio). - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees). - Instant: Processed immediately. - Request: Queued for later processing. - Big Request: A requested withdrawal exceeding half of the retention rate. - (Withdrawal) queue: A list of all requested withdrawals sorted by priority. - Request ID: The index of a withdrawal request in the queue array. - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain. - Fees Rate: Percentage of fees applied to successful withdrawals. - Usable underlyings: Amount of underlying tokens that have been deposited through expected ways and are so considered safe to use by the contract. - Transfers listeners: External contracts listening on L-Tokens transfers. - Fund wallet: Wallet managed by the Ledgity's financial team. - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request processing. Note that words between parenthesis are sometimes omitted for brevity.Deployment notice: This contract can safely receive funds immediately after initialization. (i.e., there is no way for funds to be sent to non-owned addresses). It is, however, recommended to replace ASAP owner and fund wallets with multi-sig wallets.For further details, see \\\"LToken\\\" section of whitepaper.\",\"events\":{\"APRChangeEvent(uint16)\":{\"params\":{\"newAPRUD7x3\":\"The new APR in UD7x3 format.\"}},\"ActivityEvent(int256,address,uint8,uint256,uint256,uint8,int256)\":{\"params\":{\"account\":\"The account involved in the activity.\",\"action\":\"The type of activity.\",\"amount\":\"The amount of underlying tokens involved in the activity.\",\"id\":\"ID of the involved withdrawal request or NO_ID (-1) if not applicable.\",\"newId\":\"The new ID of the request if it has been moved in the queue.\",\"newStatus\":\"The new status of the activity.\"}},\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is changed.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"MintedRewardsEvent(address,uint256,uint256)\":{\"params\":{\"account\":\"The account that received the rewards.\",\"balanceBefore\":\"The balance of the account before the minting.\",\"rewards\":\"The amount of minted rewards.\"}},\"Paused(address)\":{\"details\":\"Emitted when the pause is triggered by `account`.\"},\"TVLChangeEvent(uint256)\":{\"details\":\"TVL = realTotalSupply()\",\"params\":{\"newTVL\":\"The new TVL of the contract.\"}},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"},\"Unpaused(address)\":{\"details\":\"Emitted when the pause is lifted by `account`.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have not been yet minted to the specified account.\",\"params\":{\"account\":\"The account to check the total balance of.\"},\"returns\":{\"_0\":\"The total balance of the account.\"}},\"cancelWithdrawalRequest(uint256)\":{\"params\":{\"requestId\":\"The ID of the withdrawal request to cancel.\"}},\"decimals()\":{\"details\":\"The ERC20WrapperUpgradeable version is preferred because it mirrors the decimals amount of the underlying stablecoin token.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"deposit(uint256)\":{\"params\":{\"amount\":\"The amount of underlying tokens to deposit.\"}},\"depositFor(address,uint256)\":{\"details\":\"Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\"},\"getAPR()\":{\"returns\":{\"_0\":\"The current APR in UD7x3 format.\"}},\"getExpectedRetained()\":{\"returns\":{\"amount\":\"The expected amount of retained underlying tokens.\"}},\"getWithdrawnAmountAndFees(address,uint256)\":{\"params\":{\"account\":\"The account initiating the withdrawal.\",\"amount\":\"The amount of the withdrawal.\"}},\"globalBlacklist()\":{\"returns\":{\"_0\":\"The address of the GlobalBlacklist contract.\"}},\"globalOwner()\":{\"returns\":{\"_0\":\"The address of the GlobalOwner contract.\"}},\"globalPause()\":{\"returns\":{\"_0\":\"The address of the GlobalPause contract.\"}},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"initialize(address,address,address,address,address)\":{\"details\":\"See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\",\"params\":{\"globalBlacklist_\":\"The address of the GlobalBlacklist contract.\",\"globalOwner_\":\"The address of the GlobalOwner contract.\",\"globalPause_\":\"The address of the GlobalPause contract.\",\"underlyingToken\":\"The address of the underlying stablecoin ERC20 token.\"}},\"instantWithdrawal(uint256)\":{\"details\":\"In order to save some gas and time to users, frontends should propose this function to users only when it has been verified that it will not revert. They should propose the requestWithdrawal() function otherwise.\",\"params\":{\"amount\":\"The amount L-Tokens to withdraw.\"}},\"invested()\":{\"returns\":{\"_0\":\"The reference to the invested token contract.\"}},\"listenToTransfers(address)\":{\"details\":\"Each time a transfer occurs, the onLTokenTransfer() function of the specified contract will be called.IMPORTANT SECURITY NOTE: This method is not intended to be used with contracts that are not owned by the Ledgity team.\",\"params\":{\"listenerContract\":\"The address of the new transfers listener contract.\"}},\"name()\":{\"details\":\"Returns the name of the token.\"},\"owner()\":{\"returns\":{\"_0\":\"The address of the owner\"}},\"paused()\":{\"details\":\"Both version are the same as ERC20BaseUpgradeable.paused() mirrors GlobalPausableUpgradeable.paused(), so a random one is chosen.\",\"returns\":{\"_0\":\"Whether the contract is paused or not.\"}},\"processBigQueuedRequest(uint256)\":{\"details\":\"In contrast to non-big requests processing, this function will uses to fund wallet's balance to fill the request. This allows processing requests that are greater than retention rate without having to exceed this rate on the contract.\",\"params\":{\"requestId\":\"The ID of the big request to process.\"}},\"processQueuedRequests()\":{\"details\":\"For further details, see \\\"LToken > Withdrawals\\\" section of whitepaper.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"realBalanceOf(address)\":{\"params\":{\"account\":\"The account to check the real balance of.\"},\"returns\":{\"_0\":\"The real balance of the account.\"}},\"realTotalSupply()\":{\"returns\":{\"_0\":\"The real total supply of L-Tokens.\"}},\"recoverERC20(address,uint256)\":{\"details\":\"This override of RecoverableUpgradeable.recoverERC20() prevents the recovered token from being the underlying token.\",\"params\":{\"amount\":\"The amount of token to recover.\",\"tokenAddress\":\"The address of the token to recover.\"}},\"recoverUnderlying()\":{\"details\":\"To prevent owner from being able to drain the contract, this function only allows recovering \\\"unusable\\\" underlying tokens, i.e., tokens that have not been sent through fund() or deposit() functions.\"},\"repatriate(uint256)\":{\"details\":\"The function will revert if repatriated amount makes the contract exceeding the retention rate.\",\"params\":{\"amount\":\"The amount of underlying tokens to repatriate.\"}},\"requestWithdrawal(uint256)\":{\"details\":\"The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees paid by the withdrawer wallet.\",\"params\":{\"amount\":\"The amount L-Tokens to withdraw.\"}},\"setAPR(uint16)\":{\"params\":{\"aprUD7x3\":\"The new APR in UD7x3 format.\"}},\"setFeesRate(uint32)\":{\"params\":{\"feesRateUD7x3_\":\"The new withdrawal fee rate in UD7x3 format.\"}},\"setFund(address)\":{\"params\":{\"fund_\":\"The address of the new fund wallet.\"}},\"setLDYStaking(address)\":{\"params\":{\"ldyStakingAddress\":\"The address of the new LDYStaking contract.\"}},\"setRetentionRate(uint32)\":{\"details\":\"The retention rate is capped at 10%, which ensures that no more than 10% of deposited assets will ever be exposed in this contract (reduces attack surface).\",\"params\":{\"retentionRateUD7x3_\":\"The new retention rate in UD7x3 format.\"}},\"setWithdrawer(address)\":{\"params\":{\"withdrawer_\":\"The address of the new withdrawer wallet.\"}},\"setWithdrwalFeeInEth(uint256)\":{\"params\":{\"withdrwalFeeInEth_\":\"The new withdrawalFee in ETH.\"}},\"startRewardsRedirection(address,address)\":{\"params\":{\"from\":\"The address of the account to redirect rewards from.\",\"to\":\"The address of the account to redirect rewards to.\"}},\"stopRewardsRedirection(address,address)\":{\"params\":{\"from\":\"The address of the account to stop redirecting rewards from.\",\"to\":\"The address of the account to stop redirecting rewards to.\"}},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"returns\":{\"_0\":\"The total supply of L-Tokens.\"}},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"},\"underlying()\":{\"details\":\"Returns the address of the underlying ERC-20 token that is being wrapped.\"},\"unlistenToTransfers(address)\":{\"details\":\"The onLTokenTransfer() function of the specified contract will not be called anymore each time a L-Token transfer occurs.\",\"params\":{\"listenerContract\":\"The address of the listener contract.\"}},\"unmintedRewardsOf(address)\":{\"details\":\"This is a public implementation of InvestUpgradeable_rewardsOf(). In the context of LToken, this function returns the amount of rewards that have not been distributed/minted yet to the specified account.This is particularly useful for off-chain services to display charts and statistics, as seen in the Ledgity Yield's frontend.\",\"params\":{\"account\":\"The account to check the unminted rewards of.\"},\"returns\":{\"_0\":\"The amount of account's unminted rewards.\"}},\"upgradeTo(address)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"withdrawTo(address,uint256)\":{\"details\":\"Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\"}},\"stateVariables\":{\"frozenRequests\":{\"details\":\"If a request emitter as been blacklisted, its request is moved here to prevent it from blocking the queue.\"},\"transfersListeners\":{\"details\":\"onLTokenTransfer() functions of those contracts will be called on each transfer.\"},\"usableUnderlyings\":{\"details\":\"Are usable, only underlying tokens deposit through deposit() or fund() functions.\"}},\"title\":\"LToken\",\"version\":1},\"userdoc\":{\"events\":{\"APRChangeEvent(uint16)\":{\"notice\":\"Emitted to inform listeners about a change in the APR's value.\"},\"ActivityEvent(int256,address,uint8,uint256,uint256,uint8,int256)\":{\"notice\":\"Emitted to inform listerners about an activity related to deposits and withdrawals.\"},\"MintedRewardsEvent(address,uint256,uint256)\":{\"notice\":\"Emitted to inform listeners that some rewards have been minted.\"},\"TVLChangeEvent(uint256)\":{\"notice\":\"Emitted to inform listeners about a change in the contract's TVL.\"}},\"kind\":\"user\",\"methods\":{\"balanceOf(address)\":{\"notice\":\"Retrieves the total balance of L-Tokens that belong to the account.\"},\"cancelWithdrawalRequest(uint256)\":{\"notice\":\"Cancels a given withdrawal request. The request emitter receive back its L-Tokens and no fees will be charged.\"},\"claimFees()\":{\"notice\":\"Used by owner to claim fees generated from successful withdrawals.\"},\"decimals()\":{\"notice\":\"Required override of decimals() which is implemented by both ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\"},\"deposit(uint256)\":{\"notice\":\"Allows exchanging some underlying tokens for the same amount of L-Tokens.\"},\"depositFor(address,uint256)\":{\"notice\":\"Override of ERC20WrapperUpgradeable.depositFor() that reverts. Use deposit() function instead.\"},\"feesRateUD7x3()\":{\"notice\":\"Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\"},\"frozenRequests(uint256)\":{\"notice\":\"Holds a list of all currently frozen withdrawal requests.\"},\"fund()\":{\"notice\":\"Holds address of fund wallet (managed by Ledgity financial team).\"},\"getAPR()\":{\"notice\":\"Retrieves the most recently set APR.\"},\"getExpectedRetained()\":{\"notice\":\"Computes the maximum amount of underlying tokens that should be retained by the contract (based on retention rate).\"},\"getWithdrawnAmountAndFees(address,uint256)\":{\"notice\":\"Computes fees and net withdrawn amount for a given account withdrawing a given amount.\"},\"globalBlacklist()\":{\"notice\":\"Retrieves the address of GlobalBlacklist contract.\"},\"globalOwner()\":{\"notice\":\"Retrieves the address of GlobalOwner contract.\"},\"globalPause()\":{\"notice\":\"Retrieves the address of GlobalPause contract.\"},\"initialize(address,address,address,address,address)\":{\"notice\":\"Initializer function of the contract. It replaces the constructor() function in the context of upgradeable contracts.\"},\"instantWithdrawal(uint256)\":{\"notice\":\"Allows instaneously exchanging a given amount of L-Tokens for the same amount of underlying tokens. It will fail if the contract currently doesn't hold enough underlying tokens to cover the withdrawal.\"},\"invested()\":{\"notice\":\"Retrieves the reference to the invested token contract.\"},\"ldyStaking()\":{\"notice\":\"Holds a reference to the LDYStaking contract.\"},\"listenToTransfers(address)\":{\"notice\":\"Adds a new contract to the L-Token transfers list.\"},\"owner()\":{\"notice\":\"Override of OwnableUpgradeable.owner() that retrieves the owner's address from the GlobalOwner contract instead.\"},\"paused()\":{\"notice\":\"Required override of paused() which is implemented by both GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\"},\"processBigQueuedRequest(uint256)\":{\"notice\":\"Processes a given queued big withdrawal request (one that exceeds half of the retention rate).\"},\"processQueuedRequests()\":{\"notice\":\"Processes queued withdrawal requests until there is else no more requests, else not enough underlying tokens to continue.\"},\"realBalanceOf(address)\":{\"notice\":\"Retrieves the \\\"real\\\" balance of an account, i.e., excluding its not yet minted/distributed rewards.\"},\"realTotalSupply()\":{\"notice\":\"Returns the \\\"real\\\" amount of existing L-Tokens, i.e., excluding not yet minted withdrawal fees and L-Tokens currently in the withdrawal queue.\"},\"recoverERC20(address,uint256)\":{\"notice\":\"Recovers a specified amount of a given token address.\"},\"recoverUnderlying()\":{\"notice\":\"Recovers underlying tokens accidentally sent to the contract.\"},\"renounceOwnership()\":{\"notice\":\"Override of OwnableUpgradeable.renounceOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there.\"},\"repatriate(uint256)\":{\"notice\":\"Used by the fund wallet to repatriate underlying tokens on the contract whenever those are required to fulfill some withdrawal requests.\"},\"requestWithdrawal(uint256)\":{\"notice\":\"Allows requesting the exchange of a given amount of L-Tokens for the same amount of underlying tokens. The request will be automatically processed later.\"},\"retentionRateUD7x3()\":{\"notice\":\"Holds the retention rate in UD7x3 format.\"},\"rewardsRedirectsFromTo(address)\":{\"notice\":\"Holds active rewards redirections in both from->to and to->from[] ways.\"},\"setAPR(uint16)\":{\"notice\":\"Updates the investment APR. Restricted to owner.\"},\"setFeesRate(uint32)\":{\"notice\":\"Updates the current withdrawal fee rate.\"},\"setFund(address)\":{\"notice\":\"Updates the address of the fund wallet.\"},\"setLDYStaking(address)\":{\"notice\":\"Updates the address of LDYStaking contract.\"},\"setRetentionRate(uint32)\":{\"notice\":\"Updates the current underlying token retention rate.\"},\"setWithdrawer(address)\":{\"notice\":\"Updates the address of the withdrawer wallet.\"},\"setWithdrwalFeeInEth(uint256)\":{\"notice\":\"Updates the current withdrawalFeeInETH.\"},\"startRewardsRedirection(address,address)\":{\"notice\":\"Enables redirection of rewards from one account to another.\"},\"stopRewardsRedirection(address,address)\":{\"notice\":\"Disable an active rewards redirection.\"},\"totalQueued()\":{\"notice\":\"Holds the amount of L-Tokens currently in the withdrawal queue.\"},\"totalSupply()\":{\"notice\":\"Retrives the total supply of L-Tokens, including not yet minted withdrawal fees and L-Tokens currently in the withdrawal queue.\"},\"transferOwnership(address)\":{\"notice\":\"Override of OwnableUpgradeable.transferOwnership() that always reverts. Ownership is managed by the GlobalOwner contract and must be modified there.\"},\"transfersListeners(uint256)\":{\"notice\":\"Holds a list of contracts' references that are listening to L-Tokens transfers.\"},\"unclaimedFees()\":{\"notice\":\"Holds the amount of withdrawal fees not yet claimed by contract's owner.\"},\"unlistenToTransfers(address)\":{\"notice\":\"Removes a contract from the L-Token transfers list.\"},\"unmintedRewardsOf(address)\":{\"notice\":\"Retrieves the amount of given account's not yet minted rewards.\"},\"usableUnderlyings()\":{\"notice\":\"Holds the amount of underlying tokens considered as usable by the contract.\"},\"withdrawTo(address,uint256)\":{\"notice\":\"Override of ERC20WrapperUpgradeable.withdrawTo() that reverts. Use instantWithdrawal() or requestWithdrawal() functions instead.\"},\"withdrawalQueue(uint256)\":{\"notice\":\"Holds an ordered list of active withdrawal requests.\"},\"withdrawalQueueCursor()\":{\"notice\":\"Holds the index of the next withdrawal request to process in the queue.\"},\"withdrawer()\":{\"notice\":\"Holds address of withdrawer wallet (managed by withdrawal server).\"},\"withdrwalFeeInEth()\":{\"notice\":\"Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet.\"}},\"notice\":\"Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e., investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin. As soon as a wallet holds some L-Tokens, it starts receiving rewards in the form of additional L-Tokens, which are auto-compounded over time.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/src/LToken.sol\":\"LToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./OwnableUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership} and {acceptOwnership}.\\n *\\n * This module is used through inheritance. It will make available all functions\\n * from parent (Ownable).\\n */\\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\\n function __Ownable2Step_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable2Step_init_unchained() internal onlyInitializing {\\n }\\n address private _pendingOwner;\\n\\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Returns the address of the pending owner.\\n */\\n function pendingOwner() public view virtual returns (address) {\\n return _pendingOwner;\\n }\\n\\n /**\\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual override onlyOwner {\\n _pendingOwner = newOwner;\\n emit OwnershipTransferStarted(owner(), newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual override {\\n delete _pendingOwner;\\n super._transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev The new owner accepts the ownership transfer.\\n */\\n function acceptOwnership() public virtual {\\n address sender = _msgSender();\\n require(pendingOwner() == sender, \\\"Ownable2Step: caller is not the new owner\\\");\\n _transferOwnership(sender);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x84efb8889801b0ac817324aff6acc691d07bbee816b671817132911d287a8c63\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x4075622496acc77fd6d4de4cc30a8577a744d5c75afad33fdeacf1704d6eda98\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n *\\n * _Available since v4.8.3._\\n */\\ninterface IERC1967Upgradeable {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0x47d6e06872b12e72c79d1b5eb55842f860b5fb1207b2317c2358d2766b950a7b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822ProxiableUpgradeable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeaconUpgradeable.sol\\\";\\nimport \\\"../../interfaces/IERC1967Upgradeable.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822Upgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/StorageSlotUpgradeable.sol\\\";\\nimport \\\"../utils/Initializable.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\\n function __ERC1967Upgrade_init() internal onlyInitializing {\\n }\\n\\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\\n }\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(AddressUpgradeable.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(AddressUpgradeable.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\\n }\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x584ebdf9c1118a7c773f98788e3f3ede01982bdf8932aa06f5acc7d54876e161\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeaconUpgradeable {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized != type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../interfaces/draft-IERC1822Upgradeable.sol\\\";\\nimport \\\"../ERC1967/ERC1967UpgradeUpgradeable.sol\\\";\\nimport \\\"./Initializable.sol\\\";\\n\\n/**\\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\\n *\\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\\n * `UUPSUpgradeable` with a custom implementation of upgrades.\\n *\\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n require(address(this) != __self, \\\"Function must be called through delegatecall\\\");\\n require(_getImplementation() == __self, \\\"Function must be called through active proxy\\\");\\n _;\\n }\\n\\n /**\\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\\n * callable on the implementing contract but not through proxies.\\n */\\n modifier notDelegated() {\\n require(address(this) == __self, \\\"UUPSUpgradeable: must not be called through delegatecall\\\");\\n _;\\n }\\n\\n /**\\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\\n */\\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\\n return _IMPLEMENTATION_SLOT;\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeTo(address newImplementation) public virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\\n * encoded in `data`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {upgradeTo} and {upgradeToAndCall}.\\n *\\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\\n *\\n * ```solidity\\n * function _authorizeUpgrade(address) internal override onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xb607cb94c27e89750f5ae2ccebcb94e654e926f6125f4fd4c6262c89875118ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which allows children to implement an emergency stop\\n * mechanism that can be triggered by an authorized account.\\n *\\n * This module is used through inheritance. It will make available the\\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\\n * the functions of your contract. Note that they will not be pausable by\\n * simply including this module, only once the modifiers are put in place.\\n */\\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\\n /**\\n * @dev Emitted when the pause is triggered by `account`.\\n */\\n event Paused(address account);\\n\\n /**\\n * @dev Emitted when the pause is lifted by `account`.\\n */\\n event Unpaused(address account);\\n\\n bool private _paused;\\n\\n /**\\n * @dev Initializes the contract in unpaused state.\\n */\\n function __Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __Pausable_init_unchained() internal onlyInitializing {\\n _paused = false;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n modifier whenNotPaused() {\\n _requireNotPaused();\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n modifier whenPaused() {\\n _requirePaused();\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the contract is paused, and false otherwise.\\n */\\n function paused() public view virtual returns (bool) {\\n return _paused;\\n }\\n\\n /**\\n * @dev Throws if the contract is paused.\\n */\\n function _requireNotPaused() internal view virtual {\\n require(!paused(), \\\"Pausable: paused\\\");\\n }\\n\\n /**\\n * @dev Throws if the contract is not paused.\\n */\\n function _requirePaused() internal view virtual {\\n require(paused(), \\\"Pausable: not paused\\\");\\n }\\n\\n /**\\n * @dev Triggers stopped state.\\n *\\n * Requirements:\\n *\\n * - The contract must not be paused.\\n */\\n function _pause() internal virtual whenNotPaused {\\n _paused = true;\\n emit Paused(_msgSender());\\n }\\n\\n /**\\n * @dev Returns to normal state.\\n *\\n * Requirements:\\n *\\n * - The contract must be paused.\\n */\\n function _unpause() internal virtual whenPaused {\\n _paused = false;\\n emit Unpaused(_msgSender());\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuardUpgradeable is Initializable {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n function __ReentrancyGuard_init() internal onlyInitializing {\\n __ReentrancyGuard_init_unchained();\\n }\\n\\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n }\\n\\n function _nonReentrantAfter() private {\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return _status == _ENTERED;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xb82ef33f43b6b96109687d91b39c94573fdccaaa423fe28e8ba0977b31c023e0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20Upgradeable.sol\\\";\\nimport \\\"./extensions/IERC20MetadataUpgradeable.sol\\\";\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\\n __ERC20_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the default value returned by this function, unless\\n * it's overridden.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\",\"keccak256\":\"0xd14a627157b9a411d2410713e5dd3a377e9064bd5c194a90748bbf27ea625784\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Pausable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20Upgradeable.sol\\\";\\nimport \\\"../../../security/PausableUpgradeable.sol\\\";\\nimport \\\"../../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev ERC20 token with pausable token transfers, minting and burning.\\n *\\n * Useful for scenarios such as preventing trades until the end of an evaluation\\n * period, or having an emergency switch for freezing all token transfers in the\\n * event of a large bug.\\n *\\n * IMPORTANT: This contract does not include public pause and unpause functions. In\\n * addition to inheriting this contract, you must define both functions, invoking the\\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\\n * make the contract unpausable.\\n */\\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\\n function __ERC20Pausable_init() internal onlyInitializing {\\n __Pausable_init_unchained();\\n }\\n\\n function __ERC20Pausable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev See {ERC20-_beforeTokenTransfer}.\\n *\\n * Requirements:\\n *\\n * - the contract must not be paused.\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\\n super._beforeTokenTransfer(from, to, amount);\\n\\n require(!paused(), \\\"ERC20Pausable: token transfer while paused\\\");\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xf0bd7f71ffae5f0addd375e8511fbf2ad8ca0c9b2606c32d92bdda7d76a7a81c\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Wrapper.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC20Upgradeable.sol\\\";\\nimport \\\"../utils/SafeERC20Upgradeable.sol\\\";\\nimport \\\"../../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Extension of the ERC20 token contract to support token wrapping.\\n *\\n * Users can deposit and withdraw \\\"underlying tokens\\\" and receive a matching number of \\\"wrapped tokens\\\". This is useful\\n * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the\\n * wrapping of an existing \\\"basic\\\" ERC20 into a governance token.\\n *\\n * _Available since v4.2._\\n *\\n * @custom:storage-size 51\\n */\\nabstract contract ERC20WrapperUpgradeable is Initializable, ERC20Upgradeable {\\n IERC20Upgradeable private _underlying;\\n\\n function __ERC20Wrapper_init(IERC20Upgradeable underlyingToken) internal onlyInitializing {\\n __ERC20Wrapper_init_unchained(underlyingToken);\\n }\\n\\n function __ERC20Wrapper_init_unchained(IERC20Upgradeable underlyingToken) internal onlyInitializing {\\n require(underlyingToken != this, \\\"ERC20Wrapper: cannot self wrap\\\");\\n _underlying = underlyingToken;\\n }\\n\\n /**\\n * @dev See {ERC20-decimals}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n try IERC20MetadataUpgradeable(address(_underlying)).decimals() returns (uint8 value) {\\n return value;\\n } catch {\\n return super.decimals();\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\\n */\\n function underlying() public view returns (IERC20Upgradeable) {\\n return _underlying;\\n }\\n\\n /**\\n * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\\n */\\n function depositFor(address account, uint256 amount) public virtual returns (bool) {\\n address sender = _msgSender();\\n require(sender != address(this), \\\"ERC20Wrapper: wrapper can't deposit\\\");\\n SafeERC20Upgradeable.safeTransferFrom(_underlying, sender, address(this), amount);\\n _mint(account, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\\n */\\n function withdrawTo(address account, uint256 amount) public virtual returns (bool) {\\n _burn(_msgSender(), amount);\\n SafeERC20Upgradeable.safeTransfer(_underlying, account, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal\\n * function that can be exposed with access control if desired.\\n */\\n function _recover(address account) internal virtual returns (uint256) {\\n uint256 value = _underlying.balanceOf(address(this)) - totalSupply();\\n _mint(account, value);\\n return value;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x14bb62a60fcbc911c33ac0e5456bf31ed50b502c30be46ee15bd3b698e91bd81\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x605434219ebbe4653f703640f06969faa5a1d78f0bfef878e5ddbb1ca369ceeb\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20PermitUpgradeable {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd60f939a3ca0199014d079b4dd66aa757954334947d81eb5c1d35d7a83061ab3\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\nimport \\\"../extensions/IERC20PermitUpgradeable.sol\\\";\\nimport \\\"../../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n using AddressUpgradeable for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\n */\\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20PermitUpgradeable token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\\n * _Available since v4.9 for `string`, `bytes`._\\n */\\nlibrary StorageSlotUpgradeable {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07ac95acad040f1fb1f6120dd0aa5f702db69446e95f82613721879d30de0908\",\"license\":\"MIT\"},\"contracts/src/GlobalBlacklist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./abstracts/GlobalOwnableUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalBlacklist\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Holds a global mapping of blacklisted accounts shared by all contracts of the\\n * Ledgity Yield codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\\n * and getter functions to easily check against this global blacklist.\\n *\\n * @dev For further details, see \\\"GlobalBlacklist\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\\n /**\\n * @notice Mapping of accounts to their blacklist status.\\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\\n */\\n mapping(address => bool) private _list;\\n\\n /// @dev Emitted when `account` is blacklisted.\\n event Blacklisted(address account);\\n\\n /// @dev Emitted when `account` is unblacklisted.\\n event Unblacklisted(address account);\\n\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function initialize(address globalOwner_) public initializer {\\n __GlobalOwnable_init(globalOwner_);\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @notice Adds a given account to the blacklist.\\n * @param account The account's address to be blacklisted.\\n */\\n function blacklist(address account) external onlyOwner {\\n require(account != address(0), \\\"L20\\\");\\n _list[account] = true;\\n emit Blacklisted(account);\\n }\\n\\n /**\\n * @notice Removes a given account from the blacklist.\\n * @param account The account's address to be un-blacklisted.\\n */\\n function unBlacklist(address account) external onlyOwner {\\n _list[account] = false;\\n emit Unblacklisted(account);\\n }\\n\\n /**\\n * @notice Checks whether a given account is blacklisted.\\n * @param account Address of the account to check.\\n * @return 'true' if the account is blacklisted, 'false' otherwise\\n */\\n function isBlacklisted(address account) external view returns (bool) {\\n // Gas optimization: Avoid accessing storage if account is the zero address\\n // (e.g, during a mint or a burn of tokens)\\n if (account == address(0)) return false;\\n\\n // Else, return current account's blacklist status\\n return _list[account];\\n }\\n}\\n\",\"keccak256\":\"0x7e771076a06cfec935df22cf2d307df7e1f7df5b887976ec1dea30f8b68a878d\",\"license\":\"MIT\"},\"contracts/src/GlobalOwner.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {Ownable2StepUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalOwner\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Holds the address of a global owner account shared by all contracts of the\\n * Ledgity Yield's codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\\n * owner() function that retrieves the owner's address from this contract instead.\\n *\\n * @dev For further details, see \\\"GlobalOwner\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n */\\n function initialize() public initializer {\\n __Ownable2Step_init();\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0xa3b880c4d82e796c162c99a398b569ce4a8e6d27232014b81a6a4503718f12dc\",\"license\":\"MIT\"},\"contracts/src/GlobalPause.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./abstracts/GlobalOwnableUpgradeable.sol\\\";\\n\\n/**\\n * @title GlobalPause\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Holds a global pause state shared by all contracts of the Ledgity Yield\\n * codebase.\\n *\\n * @dev Specifically, some contracts within the codebase inherit from the\\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\\n * paused() function that retrieves the pause state from this contract instead.\\n *\\n * @dev For further details, see \\\"GlobalPause\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract GlobalPause is\\n Initializable,\\n UUPSUpgradeable,\\n GlobalOwnableUpgradeable,\\n PausableUpgradeable\\n{\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function initialize(address globalOwner_) public initializer {\\n __GlobalOwnable_init(globalOwner_);\\n __Pausable_init();\\n __UUPSUpgradeable_init();\\n }\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\\n * but restricted to contract's owner.\\n */\\n function pause() public onlyOwner {\\n _pause();\\n }\\n\\n function unpause() public onlyOwner {\\n _unpause();\\n }\\n}\\n\",\"keccak256\":\"0x9a0767e761dbd1d5800db03558c3903f229e6ef29f5fe5ff38f45fb4d7572e2e\",\"license\":\"MIT\"},\"contracts/src/LDYStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n// Contracts\\nimport {ReentrancyGuardUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\\\";\\nimport {BaseUpgradeable} from \\\"./abstracts/base/BaseUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @title LDYStaking\\n * @custom:security-contact security@ledgity.com\\n *\\n * @dev This contract implements tierOf() function from LDYStaking as it's the only\\n * one the LToken contract relies on.\\n *\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract LDYStaking is BaseUpgradeable, ReentrancyGuardUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /**\\n * @notice Represents a user staking info in array.\\n * @param stakedAmount Amount of the stake.\\n * @param unStakeAt Unstake at.\\n * @param duration Staking period in seconds.\\n * @param rewardPerTokenPaid Reward per token paid.\\n * @param rewards Rewards to be claimed.\\n */\\n struct StakingInfo {\\n uint256 stakedAmount;\\n uint256 unStakeAt;\\n uint256 duration;\\n uint256 rewardPerTokenPaid;\\n uint256 rewards;\\n }\\n\\n /**\\n * @notice Represent duration and multiplier per each stake option.\\n * @param duration Staking period in seconds.\\n * @param multiplier Token weight\\n */\\n struct StakeDurationInfo {\\n uint256 duration;\\n uint256 multiplier;\\n }\\n\\n /// @notice Decimals of multiplier\\n uint256 public constant MULTIPLIER_BASIS = 1e4;\\n\\n /// @notice Stake and Reward token.\\n IERC20Upgradeable public stakeRewardToken;\\n\\n /// @notice Minimal stake duration for perks.\\n uint256 public stakeDurationForPerks;\\n\\n /// @notice Minimal stake amount for perks.\\n uint256 public stakeAmountForPerks;\\n\\n /// @notice Stake durations info array.\\n StakeDurationInfo[] public stakeDurationInfos;\\n\\n /// @notice Duration of the rewards (in seconds).\\n uint256 public rewardsDuration;\\n\\n /// @notice Timestamp of when the rewards finish.\\n uint256 public finishAt;\\n\\n /// @notice Timestamp of the reward updated.\\n uint256 public lastUpdateTime;\\n\\n /// @notice Reward per second(total rewards / duration).\\n uint256 public rewardRatePerSec;\\n\\n /// @notice Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\\n uint256 public rewardPerTokenStored;\\n\\n /// @notice Total staked amounts.\\n uint256 public totalStaked;\\n\\n // Total staked amounts with multiplier applied\\n uint256 public totalWeightedStake;\\n\\n /// @notice User stakingInfo map, user address => array of the staking info\\n mapping(address => StakingInfo[]) public userStakingInfo;\\n\\n /// @notice Total rewards amount.\\n uint256 public totalRewards;\\n\\n /**\\n * @notice Emitted when users stake token\\n * @param user User address\\n * @param stakeIndex Latest index of user staking pool\\n * @param amount Staked amount\\n */\\n event Staked(address indexed user, uint256 stakeIndex, uint256 amount);\\n\\n /**\\n * @notice Emitted when users unstake token\\n * @param user User address\\n * @param stakeIndex User staking pool index\\n * @param amount Staked amount\\n */\\n event Unstaked(address indexed user, uint256 stakeIndex, uint256 amount);\\n\\n /**\\n * @notice Emitted when users claim rewards\\n * @param user User address\\n * @param stakeIndex User staking pool index\\n * @param reward Reward token amount\\n */\\n event RewardPaid(address indexed user, uint256 stakeIndex, uint256 reward);\\n\\n /**\\n * @notice Emitted when admin add rewards.\\n * @param rewardAmount Reward amount added by admin.\\n * @param rewardPerSec RewardRatePerSec updated.\\n */\\n event NotifiedRewardAmount(uint256 rewardAmount, uint256 rewardPerSec);\\n\\n /**\\n * @notice Holds a mapping of addresses that default to the highest staking tier.\\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\\n */\\n mapping(address => bool) public highTierAccounts;\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\\n * @dev This function is intended for setting initial values for the contract's state variables.\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param stakeRewardToken_ The address of stake and reward token(LDY token).\\n * @param stakeDurationInfos_ Available Staking Durations.\\n * @param stakeDurationForPerks_ Minimal staking duration for perks.\\n * @param stakeAmountForPerks_ Minimal staking amount for perks.\\n */\\n function initialize(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n address stakeRewardToken_,\\n StakeDurationInfo[] memory stakeDurationInfos_,\\n uint256 stakeDurationForPerks_,\\n uint256 stakeAmountForPerks_\\n ) public initializer {\\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\\n stakeRewardToken = IERC20Upgradeable(stakeRewardToken_);\\n uint stakeDurationInfosLength = stakeDurationInfos_.length;\\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\\n stakeDurationInfos.push(stakeDurationInfos_[i]);\\n }\\n stakeDurationForPerks = stakeDurationForPerks_;\\n stakeAmountForPerks = stakeAmountForPerks_;\\n }\\n\\n // --------------------\\n // MUTATIVE FUNCTIONS\\n // --------------------\\n\\n /**\\n * @notice Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\\n * @dev Emits a `Staked` event upon successful staking.\\n * @param amount The amount of tokens to stake.\\n * @param stakeDurationIndex The Index of stakeDurationInfos array.\\n */\\n function stake(\\n uint256 amount,\\n uint8 stakeDurationIndex\\n ) external nonReentrant whenNotPaused notBlacklisted(_msgSender()) {\\n require(amount > 0, \\\"amount = 0\\\");\\n require(stakeDurationIndex <= stakeDurationInfos.length - 1, \\\"Invalid staking period\\\");\\n\\n _updateReward(address(0), 0);\\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[stakeDurationIndex];\\n StakingInfo memory stakingInfo = StakingInfo({\\n stakedAmount: amount,\\n unStakeAt: block.timestamp + stakeDurationInfo.duration,\\n duration: stakeDurationInfo.duration,\\n rewardPerTokenPaid: rewardPerTokenStored,\\n rewards: 0\\n });\\n\\n // check whether account is eligible for benefit from the protocol\\n if (stakeDurationInfo.duration >= stakeDurationForPerks && amount >= stakeAmountForPerks) {\\n highTierAccounts[_msgSender()] = true;\\n }\\n\\n userStakingInfo[_msgSender()].push(stakingInfo);\\n\\n uint256 stakeIndex = userStakingInfo[_msgSender()].length - 1;\\n uint256 weightedStake = (amount * stakeDurationInfo.multiplier) / MULTIPLIER_BASIS;\\n totalWeightedStake += weightedStake;\\n totalStaked += amount;\\n\\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\\n\\n emit Staked(_msgSender(), stakeIndex, amount);\\n }\\n\\n /**\\n * @notice Withdraw staked tokens after stakeDuration has passed.\\n * @dev Emits a `Unstaked` event upon successful withdrawal.\\n * On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\\n * @param amount The amount of tokens to withdraw.\\n * @param stakeIndex The index of user staking pool\\n */\\n function unstake(\\n uint256 amount,\\n uint256 stakeIndex\\n ) external nonReentrant notBlacklisted(_msgSender()) {\\n require(amount > 0, \\\"amount = 0\\\");\\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \\\"Invalid stakeIndex\\\");\\n require(\\n block.timestamp >= userStakingInfo[_msgSender()][stakeIndex].unStakeAt,\\n \\\"Cannot unstake during staking period\\\"\\n );\\n require(\\n amount <= userStakingInfo[_msgSender()][stakeIndex].stakedAmount,\\n \\\"Insufficient unstake amount\\\"\\n );\\n\\n _updateReward(_msgSender(), stakeIndex);\\n\\n uint256 multiplier = _getMultiplier(userStakingInfo[_msgSender()][stakeIndex].duration);\\n\\n uint256 currentWeightedStake = (amount * multiplier) / MULTIPLIER_BASIS;\\n totalWeightedStake -= currentWeightedStake;\\n\\n totalStaked -= amount;\\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount -= amount;\\n\\n // check whether account is eligible for benefit from the protocol\\n if (\\n userStakingInfo[_msgSender()][stakeIndex].duration >= stakeDurationForPerks &&\\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount < stakeAmountForPerks\\n ) {\\n highTierAccounts[_msgSender()] = false;\\n }\\n\\n // remove staking info from array on full withdrawal\\n if (userStakingInfo[_msgSender()][stakeIndex].stakedAmount == 0) {\\n _claimReward(_msgSender(), stakeIndex);\\n\\n userStakingInfo[_msgSender()][stakeIndex] = userStakingInfo[_msgSender()][\\n userStakingInfo[_msgSender()].length - 1\\n ];\\n userStakingInfo[_msgSender()].pop();\\n }\\n stakeRewardToken.safeTransfer(_msgSender(), amount);\\n\\n emit Unstaked(_msgSender(), stakeIndex, amount);\\n }\\n\\n /**\\n * @notice Claim pending rewards.\\n * @dev Emits a `RewardPaid` event upon successful reward claim.\\n * @param stakeIndex The index of user staking pool.\\n */\\n function getReward(uint256 stakeIndex) external nonReentrant notBlacklisted(_msgSender()) {\\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \\\"Invalid stakeIndex\\\");\\n _updateReward(_msgSender(), stakeIndex);\\n _claimReward(_msgSender(), stakeIndex);\\n }\\n\\n // --------------------\\n // ADMIN CONFIGURATION\\n // --------------------\\n\\n /**\\n * @notice Update Rewards Duration.\\n * @dev Only callable by owner, and setting available only after rewards period.\\n * @param duration New reward duration in seconds.\\n */\\n function setRewardsDuration(uint256 duration) external onlyOwner {\\n require(finishAt < block.timestamp, \\\"reward duration is not finished\\\");\\n rewardsDuration = duration;\\n }\\n\\n /**\\n * @notice Update stakeDurationForPerks\\n * @dev Only callable by owner.\\n * @param stakeDurationForPerks_ New stakeDurationForPerks.\\n */\\n function setStakeDurationForPerks(uint256 stakeDurationForPerks_) external onlyOwner {\\n stakeDurationForPerks = stakeDurationForPerks_;\\n }\\n\\n /**\\n * @notice Update stakeAmountForPerks\\n * @dev Only callable by owner.\\n * @param stakeAmountForPerks_ New stakeDurationForPerks.\\n */\\n function setStakeAmountForPerks(uint256 stakeAmountForPerks_) external onlyOwner {\\n stakeAmountForPerks = stakeAmountForPerks_;\\n }\\n\\n /**\\n * @notice Push stakeDurationInfo\\n * @dev Only callable by owner.\\n */\\n function pushStakeDurationInfo(StakeDurationInfo memory durationInfo) external onlyOwner {\\n stakeDurationInfos.push(durationInfo);\\n }\\n\\n /**\\n * @notice Notify the contract about the amount of rewards to be distributed and update reward parameters.\\n * @dev Only callable by owner.\\n * @param amount The amount of reward to be distributed.\\n */\\n function notifyRewardAmount(uint256 amount) external onlyOwner {\\n require(rewardsDuration > 0, \\\"rewards duration is not set\\\");\\n require(amount > 0, \\\"amount = 0\\\");\\n\\n _updateReward(address(0), 0);\\n\\n if (block.timestamp >= finishAt) {\\n rewardRatePerSec = amount / rewardsDuration;\\n } else {\\n uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatePerSec;\\n rewardRatePerSec = (amount + remainingRewards) / rewardsDuration;\\n }\\n\\n require(rewardRatePerSec > 0, \\\"reward rate = 0\\\");\\n require(\\n rewardRatePerSec <=\\n (stakeRewardToken.balanceOf(address(this)) + amount - totalStaked) /\\n rewardsDuration,\\n \\\"reward amount > balance\\\"\\n );\\n\\n finishAt = block.timestamp + rewardsDuration;\\n lastUpdateTime = block.timestamp;\\n\\n totalRewards += amount;\\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\\n\\n emit NotifiedRewardAmount(amount, rewardRatePerSec);\\n }\\n\\n // --------------------\\n // VIEW FUNCTIONS\\n // --------------------\\n\\n /**\\n * @notice Get the last time when rewards were applicable for the specified reward token.\\n * @return Timestamp of the most recent rewards calculation.\\n */\\n function lastTimeRewardApplicable() public view returns (uint256) {\\n return _min(finishAt, block.timestamp);\\n }\\n\\n /**\\n * @notice Calculate the reward per token for a given reward token.\\n * @return Current reward per token.\\n */\\n function rewardPerToken() public view returns (uint256) {\\n if (totalStaked == 0) {\\n return rewardPerTokenStored;\\n }\\n\\n return\\n rewardPerTokenStored +\\n ((rewardRatePerSec * (lastTimeRewardApplicable() - lastUpdateTime) * 1e18) /\\n totalWeightedStake);\\n }\\n\\n /**\\n * @notice Calculate the user's stake pool earnings\\n * @param account Address of the user.\\n * @param stakeIndex Index of the stakePool\\n * @return Return earned amounts\\n */\\n function earned(address account, uint256 stakeIndex) public view returns (uint256) {\\n StakingInfo memory userInfo = userStakingInfo[account][stakeIndex];\\n uint256 multiplier = _getMultiplier(userInfo.duration);\\n uint256 weightedAmount = (userInfo.stakedAmount * multiplier) / MULTIPLIER_BASIS;\\n uint256 rewardsSinceLastUpdate = ((weightedAmount *\\n (rewardPerToken() - userInfo.rewardPerTokenPaid)) / 1e18);\\n return rewardsSinceLastUpdate + userInfo.rewards;\\n }\\n\\n /**\\n * @notice Get the earned rewards array for a user.\\n * @param account Address of the user.\\n * @return Return earned rewards array for a user.\\n */\\n function getEarnedUser(address account) public view returns (uint256[] memory) {\\n uint256 numberOfPools = userStakingInfo[account].length;\\n uint256[] memory earnedArray = new uint256[](numberOfPools);\\n for (uint256 index; index < numberOfPools; index++) {\\n earnedArray[index] = earned(account, index);\\n }\\n return earnedArray;\\n }\\n\\n /**\\n * @dev tierOf() function that always return that the given account is not\\n * elligible to any LDY staking tier, except if the account is in the\\n * highTierAccounts mapping.\\n * @param account The account to check the tier of.\\n */\\n function tierOf(address account) public view returns (uint256 tier) {\\n if (highTierAccounts[account]) return 3;\\n return 0;\\n }\\n\\n /**\\n * @notice Get User Stake Data.\\n * @param account The address of user.\\n * @return StakingInfo array.\\n */\\n function getUserStakes(address account) external view returns (StakingInfo[] memory) {\\n return userStakingInfo[account];\\n }\\n\\n /**\\n * @notice Get StakeDurationInfo.\\n * @param index Index of StakeDurationInfos.\\n * @return StakeDurationInfo.\\n */\\n function getStakeDurationInfo(uint256 index) external view returns (StakeDurationInfo memory) {\\n require(stakeDurationInfos.length - 1 >= index, \\\"wrong index\\\");\\n return stakeDurationInfos[index];\\n }\\n\\n /**\\n * @notice Send rewards to user.\\n * @dev This is private function, called by getReward function.\\n * @param account The address of user.\\n * @param stakeIndex The index of user staking pool.\\n */\\n function _claimReward(address account, uint256 stakeIndex) private {\\n uint256 reward = userStakingInfo[account][stakeIndex].rewards;\\n\\n if (reward > 0) {\\n userStakingInfo[account][stakeIndex].rewards = 0;\\n totalRewards -= reward;\\n stakeRewardToken.safeTransfer(account, reward);\\n emit RewardPaid(account, stakeIndex, reward);\\n }\\n }\\n\\n /**\\n * @notice Calculate and update user rewards per stakeIndex.\\n * @dev this is private function, called by stake, unstake, getRewards, and notifyRewardAmount functions.\\n * @param account The address of user.\\n * @param stakeIndex The index of user staking pool.\\n */\\n function _updateReward(address account, uint256 stakeIndex) private {\\n rewardPerTokenStored = rewardPerToken();\\n lastUpdateTime = lastTimeRewardApplicable();\\n\\n if (account != address(0)) {\\n userStakingInfo[account][stakeIndex].rewards = earned(account, stakeIndex);\\n userStakingInfo[account][stakeIndex].rewardPerTokenPaid = rewardPerTokenStored;\\n }\\n }\\n\\n /**\\n * @notice Get multiplier from stakeDurationInfo based on duration\\n * @param duration Stake Duration\\n */\\n function _getMultiplier(uint256 duration) private view returns (uint256) {\\n uint256 stakeDurationInfosLength = stakeDurationInfos.length;\\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[i];\\n if (duration == stakeDurationInfo.duration) {\\n return stakeDurationInfo.multiplier;\\n }\\n }\\n return 0;\\n }\\n\\n /**\\n * @notice Take minimum value between x and y.\\n */\\n function _min(uint256 x, uint256 y) private pure returns (uint256) {\\n return x <= y ? x : y;\\n }\\n}\\n\",\"keccak256\":\"0x7e6eba9f67c4a0ad1ade18149d04fe01a53bae4cc3a898a8ab0b347c1d036cc5\",\"license\":\"MIT\"},\"contracts/src/LToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n// Contracts\\nimport {ERC20WrapperUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\\\";\\nimport \\\"./abstracts/base/ERC20BaseUpgradeable.sol\\\";\\nimport {InvestUpgradeable} from \\\"./abstracts/InvestUpgradeable.sol\\\";\\nimport {LDYStaking} from \\\"./LDYStaking.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport {SUD} from \\\"./libs/SUD.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport {IERC20MetadataUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\nimport {ITransfersListener} from \\\"./interfaces/ITransfersListener.sol\\\";\\n\\n/**\\n * @title LToken\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e.,\\n * investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin.\\n * As soon as a wallet holds some L-Tokens, it starts receiving rewards in\\n * the form of additional L-Tokens, which are auto-compounded over time.\\n *\\n * @dev Definitions:\\n * - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio).\\n * - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees).\\n * - Instant: Processed immediately.\\n * - Request: Queued for later processing.\\n * - Big Request: A requested withdrawal exceeding half of the retention rate.\\n * - (Withdrawal) queue: A list of all requested withdrawals sorted by priority.\\n * - Request ID: The index of a withdrawal request in the queue array.\\n * - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain.\\n * - Fees Rate: Percentage of fees applied to successful withdrawals.\\n * - Usable underlyings: Amount of underlying tokens that have been deposited through\\n * expected ways and are so considered safe to use by the contract.\\n * - Transfers listeners: External contracts listening on L-Tokens transfers.\\n * - Fund wallet: Wallet managed by the Ledgity's financial team.\\n * - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request\\n * processing.\\n *\\n * Note that words between parenthesis are sometimes omitted for brevity.\\n *\\n * @dev Deployment notice:\\n * This contract can safely receive funds immediately after initialization. (i.e., there\\n * is no way for funds to be sent to non-owned addresses). It is, however, recommended to\\n * replace ASAP owner and fund wallets with multi-sig wallets.\\n *\\n * @dev For further details, see \\\"LToken\\\" section of whitepaper.\\n * @custom:oz-upgrades-unsafe-allow external-library-linking\\n * @custom:security-contact security@ledgity.com\\n */\\ncontract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @dev Represents type of actions triggering ActivityEvent events.\\n enum Action {\\n Deposit,\\n Withdraw\\n }\\n\\n /// @dev Represents different status of actions triggering ActivityEvent events.\\n enum Status {\\n Queued,\\n Cancelled,\\n Success,\\n Moved\\n }\\n\\n /**\\n * @notice Represents a withdrawal request in the queue.\\n * @dev A request fits in a single storage slot (32 bytes).\\n * @param account The account that initiated the request.\\n * @param amount The amount of underlying tokens requested.\\n */\\n struct WithdrawalRequest {\\n address account; // 20 bytes\\n uint96 amount; // 12 bytes\\n }\\n\\n /// @notice Upper limit of retention rate.\\n uint32 private constant MAX_RETENTION_RATE_UD7x3 = 10 * 10 ** 3; // 10%\\n\\n /// @notice Upper limit of fees rate.\\n uint32 private constant MAX_FEES_RATE_UD7x3 = 20 * 10 ** 3; // 20%\\n\\n /// @notice Used in activity events to represent the absence of request ID.\\n int256 private constant NO_ID = -1;\\n\\n /// @notice Holds a reference to the LDYStaking contract.\\n LDYStaking public ldyStaking;\\n\\n /// @notice Holds address of withdrawer wallet (managed by withdrawal server).\\n address payable public withdrawer;\\n\\n /// @notice Holds address of fund wallet (managed by Ledgity financial team).\\n address public fund;\\n\\n /// @notice Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\\n uint32 public feesRateUD7x3;\\n\\n /// @notice Holds the retention rate in UD7x3 format.\\n uint32 public retentionRateUD7x3;\\n\\n /// @notice Holds the amount of withdrawal fees not yet claimed by contract's owner.\\n uint256 public unclaimedFees;\\n\\n /// @notice Holds the amount of L-Tokens currently in the withdrawal queue.\\n uint256 public totalQueued;\\n\\n /**\\n * @notice Holds the amount of underlying tokens considered as usable by the contract.\\n * @dev Are usable, only underlying tokens deposit through deposit() or fund() functions.\\n */\\n uint256 public usableUnderlyings;\\n\\n /// @notice Holds an ordered list of active withdrawal requests.\\n WithdrawalRequest[] public withdrawalQueue;\\n\\n /// @notice Holds the index of the next withdrawal request to process in the queue.\\n uint256 public withdrawalQueueCursor;\\n\\n /**\\n * @notice Holds a list of all currently frozen withdrawal requests.\\n * @dev If a request emitter as been blacklisted, its request is moved here to prevent\\n * it from blocking the queue.\\n */\\n WithdrawalRequest[] public frozenRequests;\\n\\n /**\\n * @notice Holds a list of contracts' references that are listening to L-Tokens transfers.\\n * @dev onLTokenTransfer() functions of those contracts will be called on each transfer.\\n */\\n ITransfersListener[] public transfersListeners;\\n\\n /**\\n * @notice Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet.\\n */\\n uint256 public withdrwalFeeInEth;\\n\\n /**\\n * @notice Emitted to inform listeners about a change in the contract's TVL.\\n * @dev TVL = realTotalSupply()\\n * @param newTVL The new TVL of the contract.\\n */\\n event TVLChangeEvent(uint256 newTVL);\\n\\n /**\\n * @notice Emitted to inform listerners about an activity related to deposits and withdrawals.\\n * @param id ID of the involved withdrawal request or NO_ID (-1) if not applicable.\\n * @param account The account involved in the activity.\\n * @param action The type of activity.\\n * @param amount The amount of underlying tokens involved in the activity.\\n * @param newStatus The new status of the activity.\\n * @param newId The new ID of the request if it has been moved in the queue.\\n */\\n event ActivityEvent(\\n int256 indexed id,\\n address indexed account,\\n Action indexed action,\\n uint256 amount,\\n uint256 amountAfterFees,\\n Status newStatus,\\n int256 newId\\n );\\n\\n /**\\n * @notice Emitted to inform listeners that some rewards have been minted.\\n * @param account The account that received the rewards.\\n * @param balanceBefore The balance of the account before the minting.\\n * @param rewards The amount of minted rewards.\\n */\\n event MintedRewardsEvent(address indexed account, uint256 balanceBefore, uint256 rewards);\\n\\n /// @notice Reverts if the function caller is not the withdrawer wallet.\\n modifier onlyWithdrawer() {\\n require(_msgSender() == withdrawer, \\\"L39\\\");\\n _;\\n }\\n\\n /// @notice Reverts if the function caller is not the fund wallet.\\n modifier onlyFund() {\\n require(_msgSender() == fund, \\\"L40\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializer function of the contract. It replaces the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param underlyingToken The address of the underlying stablecoin ERC20 token.\\n */\\n function initialize(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n address ldyStaking_,\\n address underlyingToken\\n ) public initializer {\\n // Initialize ERC20 base.\\n string memory underlyingSymbol = IERC20MetadataUpgradeable(underlyingToken).symbol();\\n __ERC20Base_init(\\n globalOwner_,\\n globalPause_,\\n globalBlacklist_,\\n string(abi.encodePacked(\\\"Ledgity \\\", underlyingSymbol)),\\n string(abi.encodePacked(\\\"L\\\", underlyingSymbol))\\n );\\n\\n // IMPORTANT: Below calls must not be restricted to owner at any point.\\n // This is because the GlobalOwner contract may not be a fresh one, and so\\n // the contract deployer may not be the owner anymore after ERC20Base init.\\n\\n // Initialize other parents contracts.\\n __ERC20Wrapper_init(IERC20Upgradeable(underlyingToken));\\n __Invest_init_unchained(address(this));\\n\\n // Set LDYStaking contract\\n ldyStaking = LDYStaking(ldyStaking_);\\n\\n // Set initial withdrawal fees rate to 0.3%\\n feesRateUD7x3 = 300;\\n\\n // Set initial retention rate to 10%\\n retentionRateUD7x3 = 10_000;\\n\\n // Default withdrawer and fund wallet to contract owner address. This prevents\\n // any loss of funds if a deposit/withdrawal is made before those are manually set.\\n withdrawer = payable(owner());\\n fund = payable(owner());\\n\\n // Set initial withdrwalFeeInEth\\n withdrwalFeeInEth = 0.00075 * 1e18;\\n }\\n\\n /**\\n * @notice Required override of decimals() which is implemented by both\\n * ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\\n * @dev The ERC20WrapperUpgradeable version is preferred because it mirrors the\\n * decimals amount of the underlying stablecoin token.\\n * @inheritdoc ERC20WrapperUpgradeable\\n */\\n function decimals()\\n public\\n view\\n override(ERC20Upgradeable, ERC20WrapperUpgradeable)\\n returns (uint8)\\n {\\n return ERC20WrapperUpgradeable.decimals();\\n }\\n\\n /**\\n * @notice Required override of paused() which is implemented by both\\n * GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\\n * @dev Both version are the same as ERC20BaseUpgradeable.paused() mirrors\\n * GlobalPausableUpgradeable.paused(), so a random one is chosen.\\n * @inheritdoc GlobalPausableUpgradeable\\n */\\n function paused()\\n public\\n view\\n virtual\\n override(GlobalPausableUpgradeable, ERC20BaseUpgradeable)\\n returns (bool)\\n {\\n return GlobalPausableUpgradeable.paused();\\n }\\n\\n /**\\n * @notice Updates the current withdrawal fee rate.\\n * @param feesRateUD7x3_ The new withdrawal fee rate in UD7x3 format.\\n */\\n function setFeesRate(uint32 feesRateUD7x3_) public onlyOwner {\\n require(feesRateUD7x3_ <= MAX_FEES_RATE_UD7x3, \\\"L88\\\");\\n feesRateUD7x3 = feesRateUD7x3_;\\n }\\n\\n /**\\n * @notice Updates the current withdrawalFeeInETH.\\n * @param withdrwalFeeInEth_ The new withdrawalFee in ETH.\\n */\\n function setWithdrwalFeeInEth(uint256 withdrwalFeeInEth_) public onlyOwner {\\n require(withdrwalFeeInEth <= MAX_FEES_RATE_UD7x3, \\\"L88\\\");\\n withdrwalFeeInEth = withdrwalFeeInEth_;\\n }\\n\\n /**\\n * @notice Updates the current underlying token retention rate.\\n * @dev The retention rate is capped at 10%, which ensures that no more than 10% of\\n * deposited assets will ever be exposed in this contract (reduces attack surface).\\n * @param retentionRateUD7x3_ The new retention rate in UD7x3 format.\\n */\\n function setRetentionRate(uint32 retentionRateUD7x3_) public onlyOwner {\\n require(retentionRateUD7x3_ <= MAX_RETENTION_RATE_UD7x3, \\\"L41\\\");\\n retentionRateUD7x3 = retentionRateUD7x3_;\\n }\\n\\n /**\\n * @notice Updates the address of LDYStaking contract.\\n * @param ldyStakingAddress The address of the new LDYStaking contract.\\n */\\n function setLDYStaking(address ldyStakingAddress) public onlyOwner {\\n ldyStaking = LDYStaking(ldyStakingAddress);\\n }\\n\\n /**\\n * @notice Updates the address of the withdrawer wallet.\\n * @param withdrawer_ The address of the new withdrawer wallet.\\n */\\n function setWithdrawer(address payable withdrawer_) public onlyOwner {\\n // Ensure address is not the zero address (pre-processing fees would be lost else)\\n require(withdrawer_ != address(0), \\\"L63\\\");\\n\\n // Set new withdrawer wallet's address\\n withdrawer = withdrawer_;\\n }\\n\\n /**\\n * @notice Updates the address of the fund wallet.\\n * @param fund_ The address of the new fund wallet.\\n */\\n function setFund(address payable fund_) public onlyOwner {\\n // Ensure address is not the zero address (deposited tokens would be lost else)\\n require(fund_ != address(0), \\\"L64\\\");\\n\\n // Set new fund wallet's address\\n fund = fund_;\\n }\\n\\n /**\\n * @notice Adds a new contract to the L-Token transfers list.\\n * @dev Each time a transfer occurs, the onLTokenTransfer() function of the\\n * specified contract will be called.\\n * @dev IMPORTANT SECURITY NOTE: This method is not intended to be used with\\n * contracts that are not owned by the Ledgity team.\\n * @param listenerContract The address of the new transfers listener contract.\\n */\\n function listenToTransfers(address listenerContract) public onlyOwner {\\n transfersListeners.push(ITransfersListener(listenerContract));\\n }\\n\\n /**\\n * @notice Removes a contract from the L-Token transfers list.\\n * @dev The onLTokenTransfer() function of the specified contract will not be called\\n * anymore each time a L-Token transfer occurs.\\n * @param listenerContract The address of the listener contract.\\n */\\n function unlistenToTransfers(address listenerContract) public onlyOwner {\\n // Find index of listener contract in transferListeners array\\n int256 index = -1;\\n uint256 transfersListenersLength = transfersListeners.length;\\n for (uint256 i = 0; i < transfersListenersLength; i++) {\\n if (address(transfersListeners[i]) == listenerContract) {\\n index = int256(i);\\n break;\\n }\\n }\\n\\n // Revert if given contract wasn't listening to transfers\\n require(index > -1, \\\"L42\\\");\\n\\n // Else, remove transfers listener contract from listeners array\\n transfersListeners[uint256(index)] = transfersListeners[transfersListenersLength - 1];\\n transfersListeners.pop();\\n }\\n\\n /**\\n * @notice Retrieves the amount of given account's not yet minted rewards.\\n * @dev This is a public implementation of InvestUpgradeable_rewardsOf(). In the\\n * context of LToken, this function returns the amount of rewards that have not been\\n * distributed/minted yet to the specified account.\\n * @dev This is particularly useful for off-chain services to display charts and\\n * statistics, as seen in the Ledgity Yield's frontend.\\n * @param account The account to check the unminted rewards of.\\n * @return The amount of account's unminted rewards.\\n */\\n function unmintedRewardsOf(address account) public view returns (uint256) {\\n return _rewardsOf(account, true);\\n }\\n\\n /**\\n * @notice Retrieves the \\\"real\\\" balance of an account, i.e., excluding its not yet\\n * minted/distributed rewards.\\n * @param account The account to check the real balance of.\\n * @return The real balance of the account.\\n */\\n function realBalanceOf(address account) public view returns (uint256) {\\n return super.balanceOf(account);\\n }\\n\\n /**\\n * @notice Retrieves the total balance of L-Tokens that belong to the account.\\n * @dev This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have\\n * not been yet minted to the specified account.\\n * @param account The account to check the total balance of.\\n * @return The total balance of the account.\\n */\\n function balanceOf(address account) public view override returns (uint256) {\\n return realBalanceOf(account) + unmintedRewardsOf(account);\\n }\\n\\n /**\\n * @notice Returns the \\\"real\\\" amount of existing L-Tokens, i.e., excluding not yet\\n * minted withdrawal fees and L-Tokens currently in the withdrawal queue.\\n * @return The real total supply of L-Tokens.\\n */\\n function realTotalSupply() public view returns (uint256) {\\n return super.totalSupply();\\n }\\n\\n /**\\n * @notice Retrives the total supply of L-Tokens, including not yet minted withdrawal\\n * fees and L-Tokens currently in the withdrawal queue.\\n * @return The total supply of L-Tokens.\\n */\\n function totalSupply() public view override returns (uint256) {\\n return realTotalSupply() + totalQueued + unclaimedFees;\\n }\\n\\n /**\\n * @notice Recovers a specified amount of a given token address.\\n * @dev This override of RecoverableUpgradeable.recoverERC20() prevents the recovered\\n * token from being the underlying token.\\n * @inheritdoc RecoverableUpgradeable\\n */\\n function recoverERC20(address tokenAddress, uint256 amount) public override onlyOwner {\\n // Ensure the token is not the underlying token\\n require(tokenAddress != address(underlying()), \\\"L43\\\");\\n\\n // Proceed to recovery\\n super.recoverERC20(tokenAddress, amount);\\n }\\n\\n /**\\n * @notice Recovers underlying tokens accidentally sent to the contract.\\n * @dev To prevent owner from being able to drain the contract, this function only\\n * allows recovering \\\"unusable\\\" underlying tokens, i.e., tokens that have not been\\n * sent through fund() or deposit() functions.\\n */\\n function recoverUnderlying() external onlyOwner {\\n // Compute the recoverable amount by taking the difference between the contract's\\n // balance and the amount of usable underlying tokens\\n uint256 recoverableAmount = underlying().balanceOf(address(this)) - usableUnderlyings;\\n\\n // Revert if there is nothing to recover\\n require(recoverableAmount > 0, \\\"L44\\\");\\n\\n // Else, proceed to underlying tokens recovery\\n super.recoverERC20(address(underlying()), recoverableAmount);\\n }\\n\\n /**\\n * @notice Retrieves the amount of underlying tokens invested by the given account.\\n * @dev Implementing this function is required by the InvestUpgradeable contract. In\\n * LToken contract, the investment of an account is equal to its real balance.\\n * @inheritdoc InvestUpgradeable\\n */\\n function _investmentOf(address account) internal view override returns (uint256) {\\n return realBalanceOf(account);\\n }\\n\\n /**\\n * @notice Distributes a specified amount of rewards (in L-Tokens) to a given account.\\n * @dev Implementing this function is required by the InvestUpgradeable contract so\\n * it can distribute rewards to accounts before each period reset.\\n * @dev InvestUpgradeable contract already ensure that amount > 0.\\n * @inheritdoc InvestUpgradeable\\n */\\n function _distributeRewards(address account, uint256 amount) internal override returns (bool) {\\n // Inform listeners of the rewards minting\\n emit MintedRewardsEvent(account, realBalanceOf(account), amount);\\n\\n // Mint L-Tokens rewards to account\\n _mint(account, amount);\\n\\n // Return true indicating to InvestUpgradeable that the rewards have been distributed\\n return true;\\n }\\n\\n /**\\n * @notice Override of ERC20._beforeTokenTransfer() to integrate with InvestUpgradeable.\\n * @dev This overriden version ensure that _beforeInvestmentChange() hook is properly\\n * called each time an account's balance is going to change.\\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\\n * already included in ERC20BaseUpgradeable._beforeTokenTransfer().\\n * @inheritdoc ERC20BaseUpgradeable\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal override(ERC20Upgradeable, ERC20BaseUpgradeable) {\\n ERC20BaseUpgradeable._beforeTokenTransfer(from, to, amount);\\n\\n // Invoke _beforeInvestmentChange() hook for non-zero accounts\\n if (from != address(0)) _beforeInvestmentChange(from, true);\\n if (to != address(0)) _beforeInvestmentChange(to, true);\\n }\\n\\n /**\\n * @notice Override of ERC20._afterTokenTransfer() to notify all transfers listeners.\\n * @dev This overriden version will trigger onLTokenTransfer() functions of all\\n * transfers listeners.\\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\\n * already checked in _beforeTokenTransfer().\\n * @inheritdoc ERC20Upgradeable\\n */\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\\n super._afterTokenTransfer(from, to, amount);\\n\\n // If some L-Token have been burned/minted, inform listeners of a TVL change\\n if (from == address(0) || to == address(0)) emit TVLChangeEvent(totalSupply());\\n\\n // Trigger onLTokenTransfer() functions of all the transfers listeners\\n for (uint256 i = 0; i < transfersListeners.length; i++) {\\n transfersListeners[i].onLTokenTransfer(from, to, amount);\\n }\\n }\\n\\n /**\\n * @notice Computes the maximum amount of underlying tokens that should be retained\\n * by the contract (based on retention rate).\\n * @return amount The expected amount of retained underlying tokens.\\n */\\n function getExpectedRetained() public view returns (uint256 amount) {\\n // Cache invested token's decimals number\\n uint256 d = SUD.decimalsOf(address(invested()));\\n\\n // Convert totalSupply and retentionRate to SUD\\n uint256 totalSupplySUD = SUD.fromAmount(totalSupply(), d);\\n uint256 retentionRateSUD = SUD.fromRate(retentionRateUD7x3, d);\\n\\n // Compute and return expected retained amount\\n uint256 expectedRetainedSUD = (totalSupplySUD * retentionRateSUD) / SUD.fromInt(100, d);\\n return SUD.toAmount(expectedRetainedSUD, d);\\n }\\n\\n /// @notice Transfers underlying tokens exceeding the retention rate to the fund wallet.\\n function _transferExceedingToFund() internal {\\n // Retrieve the expected amount retained\\n uint256 expectedRetained = getExpectedRetained();\\n\\n // If usable underlyings are less than or equal to expected retained, return\\n if (usableUnderlyings <= expectedRetained) return;\\n\\n // Else, exceeding amount is equal to difference between those values\\n uint256 exceedingAmount = usableUnderlyings - expectedRetained;\\n\\n // Decrease usable underlyings amount accordingly\\n usableUnderlyings -= exceedingAmount;\\n\\n // Transfer the exceeding amount to the fund wallet\\n underlying().safeTransfer(fund, exceedingAmount);\\n }\\n\\n /**\\n * @notice Override of ERC20WrapperUpgradeable.withdrawTo() that reverts.\\n * Use instantWithdrawal() or requestWithdrawal() functions instead.\\n * @inheritdoc ERC20WrapperUpgradeable\\n */\\n function withdrawTo(address account, uint256 amount) public pure override returns (bool) {\\n account; // Silence unused variable compiler warning\\n amount;\\n revert(\\\"L45\\\");\\n }\\n\\n /**\\n * @notice Override of ERC20WrapperUpgradeable.depositFor() that reverts.\\n * Use deposit() function instead.\\n * @inheritdoc ERC20WrapperUpgradeable\\n */\\n function depositFor(address account, uint256 amount) public pure override returns (bool) {\\n account; // Silence unused variable compiler warning\\n amount;\\n revert(\\\"L46\\\");\\n }\\n\\n /**\\n * @notice Allows exchanging some underlying tokens for the same amount of L-Tokens.\\n * @param amount The amount of underlying tokens to deposit.\\n */\\n function deposit(uint256 amount) public whenNotPaused notBlacklisted(_msgSender()) {\\n // Ensure the account has enough underlying tokens to deposit\\n require(underlying().balanceOf(_msgSender()) >= amount, \\\"L47\\\");\\n\\n // Update usable underlyings balance accordingly\\n usableUnderlyings += amount;\\n\\n // Inform listeners of the deposit activity event\\n emit ActivityEvent(\\n NO_ID,\\n _msgSender(),\\n Action.Deposit,\\n amount,\\n amount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Receive underlying tokens and mint L-Tokens to the account in a 1:1 ratio\\n super.depositFor(_msgSender(), amount);\\n\\n // Transfer exceeding underlying tokens to the fund wallet\\n _transferExceedingToFund();\\n }\\n\\n /**\\n * @notice Computes fees and net withdrawn amount for a given account withdrawing a\\n * given amount.\\n * @param account The account initiating the withdrawal.\\n * @param amount The amount of the withdrawal.\\n */\\n function getWithdrawnAmountAndFees(\\n address account,\\n uint256 amount\\n ) public view returns (uint256 withdrawnAmount, uint256 fees) {\\n // If the account is eligible to staking tier 2, no fees are applied\\n if (ldyStaking.tierOf(account) >= 2) return (amount, 0);\\n\\n // Cache invested token's decimals number\\n uint256 d = SUD.decimalsOf(address(invested()));\\n\\n // Convert amount and fees rate to SUD\\n uint256 amountSUD = SUD.fromAmount(amount, d);\\n uint256 feesRateSUD = SUD.fromRate(feesRateUD7x3, d);\\n\\n // Compute fees and withdrawn amount (initial amount minus fees)\\n uint256 feesSUD = (amountSUD * feesRateSUD) / SUD.fromInt(100, d);\\n fees = SUD.toAmount(feesSUD, d);\\n withdrawnAmount = amount - fees;\\n }\\n\\n /**\\n * @notice Allows instaneously exchanging a given amount of L-Tokens for the same\\n * amount of underlying tokens. It will fail if the contract currently doesn't hold\\n * enough underlying tokens to cover the withdrawal.\\n * @dev In order to save some gas and time to users, frontends should propose this\\n * function to users only when it has been verified that it will not revert. They\\n * should propose the requestWithdrawal() function otherwise.\\n * @param amount The amount L-Tokens to withdraw.\\n */\\n function instantWithdrawal(uint256 amount) external whenNotPaused notBlacklisted(_msgSender()) {\\n // Ensure the account has enough L-Tokens to withdraw\\n require(amount <= balanceOf(_msgSender()), \\\"L48\\\");\\n\\n // Can the contract cover this withdrawal plus all already queued requests?\\n bool cond1 = totalQueued + amount <= usableUnderlyings;\\n\\n // Is caller eligible to staking tier 2 and the contract can cover this withdrawal?\\n bool cond2 = ldyStaking.tierOf(_msgSender()) >= 2 && amount <= usableUnderlyings;\\n\\n // Revert if conditions are not met for the withdrawal to be processed instantaneously\\n if (!(cond1 || cond2)) revert(\\\"L49\\\");\\n\\n // Else, retrieve withdrawal fees and net withdrawn amount\\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(_msgSender(), amount);\\n\\n // Increase unclaimed fees amount accordingly\\n unclaimedFees += fees;\\n\\n // Decrease usable underlyings balance accordingly\\n usableUnderlyings -= withdrawnAmount;\\n\\n // Inform listeners of this instant withdrawal activity event\\n emit ActivityEvent(\\n NO_ID,\\n _msgSender(),\\n Action.Withdraw,\\n amount,\\n withdrawnAmount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Burn withdrawal fees from the account\\n _burn(_msgSender(), fees);\\n\\n // Burn account's withdrawn L-Tokens and transfer to it underlying tokens in a 1:1 ratio\\n super.withdrawTo(_msgSender(), withdrawnAmount);\\n }\\n\\n /**\\n * @notice Allows requesting the exchange of a given amount of L-Tokens for the same\\n * amount of underlying tokens. The request will be automatically processed later.\\n * @dev The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees\\n * paid by the withdrawer wallet.\\n * @param amount The amount L-Tokens to withdraw.\\n */\\n function requestWithdrawal(\\n uint256 amount\\n ) public payable whenNotPaused notBlacklisted(_msgSender()) {\\n // Ensure the account has enough L-Tokens to withdraw\\n require(amount <= balanceOf(_msgSender()), \\\"L53\\\");\\n\\n // Ensure the requested amount doesn't overflow uint96\\n require(amount <= type(uint96).max, \\\"L54\\\");\\n\\n // Ensure the sender attached the pre-paid processing gas fees\\n require(msg.value == withdrwalFeeInEth, \\\"L55\\\");\\n\\n // Create withdrawal request data\\n WithdrawalRequest memory request = WithdrawalRequest({\\n account: _msgSender(),\\n amount: uint96(amount)\\n });\\n\\n // Will hold the request ID\\n uint256 requestId;\\n\\n // Append request to the withdrawal queue:\\n // - At the beginning, if account is eligible to staking tier 2 and cursor is not 0\\n if (ldyStaking.tierOf(_msgSender()) >= 2 && withdrawalQueueCursor > 0) {\\n withdrawalQueueCursor--;\\n requestId = withdrawalQueueCursor;\\n withdrawalQueue[requestId] = request;\\n }\\n // - At the end else\\n else {\\n withdrawalQueue.push(request);\\n requestId = withdrawalQueue.length - 1;\\n }\\n\\n // Increase total amount queued accordingly\\n totalQueued += amount;\\n\\n // Inform listeners of this new queued withdrawal activity event\\n emit ActivityEvent(\\n int256(requestId),\\n _msgSender(),\\n Action.Withdraw,\\n amount,\\n amount,\\n Status.Queued,\\n NO_ID\\n );\\n\\n // Burn withdrawal L-Tokens amount from account's balance\\n _burn(_msgSender(), amount);\\n\\n // Forward pre-paid processing gas fees to the withdrawer wallet\\n (bool sent, ) = withdrawer.call{value: msg.value}(\\\"\\\");\\n require(sent, \\\"L56\\\");\\n }\\n\\n /**\\n * @notice Processes queued withdrawal requests until there is else no more requests,\\n * else not enough underlying tokens to continue.\\n * @dev For further details, see \\\"LToken > Withdrawals\\\" section of whitepaper.\\n */\\n function processQueuedRequests() external onlyWithdrawer whenNotPaused {\\n // Accumulators variables, will be written on-chain after the loop\\n uint256 cumulatedFees = 0;\\n uint256 cumulatedWithdrawnAmount = 0;\\n uint256 nextRequestId = withdrawalQueueCursor;\\n\\n // Cache queue length to avoid multiple SLOADs and avoid infinite loop as big\\n // requests are increasing the queue length when moved at the end of the queue.\\n uint256 queueLength = withdrawalQueue.length;\\n\\n // Iterate over requests to be processed\\n while (nextRequestId < queueLength) {\\n // Stop processing requests if there is not enough gas left to continue the\\n // loop and properly end the function call. This prevents an attacker from\\n // blocking the withdrawal processing by creating a ton of tiny requests so\\n // this function call cannot fit anymore in block gas limit.\\n if (gasleft() < 45000) break;\\n\\n // Retrieve request data\\n WithdrawalRequest memory request = withdrawalQueue[nextRequestId];\\n\\n // Skip empty request (processed big requests or cancelled requests)\\n if (request.account == address(0)) {}\\n //\\n // If account has been blacklisted since request emission\\n else if (isBlacklisted(request.account)) {\\n // Remove request from queue\\n delete withdrawalQueue[nextRequestId];\\n\\n // Append request in the frozen requests list\\n frozenRequests.push(request);\\n }\\n //\\n // Or if request is a big request, move it at the end of the queue for now.\\n // This request will be processed manually later using processBigQueuedRequest()\\n else if (request.amount > getExpectedRetained() / 2) {\\n // Inform listeners of this queued request being moved at the end of the queue\\n emit ActivityEvent(\\n int256(nextRequestId),\\n _msgSender(),\\n Action.Withdraw,\\n request.amount,\\n request.amount,\\n Status.Moved,\\n int256(withdrawalQueue.length)\\n );\\n\\n // Remove request from queue\\n delete withdrawalQueue[nextRequestId];\\n\\n // Append request at the end of the queue\\n withdrawalQueue.push(request);\\n }\\n //\\n // Else, continue request processing\\n else {\\n // Retrieve withdrawal fees and net withdrawn amount\\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\\n request.account,\\n request.amount\\n );\\n\\n // Break if the contract doesn't hold enough funds to cover the request\\n if (withdrawnAmount > usableUnderlyings - cumulatedWithdrawnAmount) break;\\n\\n // Accumulate fees and withdrawn amount\\n cumulatedFees += fees;\\n cumulatedWithdrawnAmount += withdrawnAmount;\\n\\n // Inform listeners of this queued withdrawal processing activity event\\n emit ActivityEvent(\\n int256(nextRequestId),\\n request.account,\\n Action.Withdraw,\\n request.amount,\\n withdrawnAmount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Remove request from queue\\n delete withdrawalQueue[nextRequestId];\\n\\n // Transfer underlying tokens to account. Burning L-Tokens is not required\\n // as equestWithdrawal() already did it.\\n // Security note: Re-entrancy warning are disabled as the request has\\n // just been deleted from the queue, it will so be skipped if trying to\\n // process it again.\\n // slither-disable-next-line reentrancy-no-eth\\n underlying().safeTransfer(request.account, withdrawnAmount);\\n }\\n\\n // Increment next request ID\\n nextRequestId++;\\n }\\n\\n // Increase unclaimed fees by the amount of cumulated fees\\n unclaimedFees += cumulatedFees;\\n\\n // Decrease usable underlyings by the cumulated amount of withdrawn underlyings\\n usableUnderlyings -= cumulatedWithdrawnAmount;\\n\\n // Decrease total amount queued by the cumulated amount requested\\n totalQueued -= cumulatedWithdrawnAmount + cumulatedFees;\\n\\n // Update new queue cursor\\n withdrawalQueueCursor = nextRequestId;\\n\\n // Retention rate cannot exceeds as the withdrawal decreases both usable\\n // underlyings and expected retained amounts by the same number and as the\\n // expected retained amount is a subset of usable underlyings amount.\\n }\\n\\n /**\\n * @notice Processes a given queued big withdrawal request (one that exceeds half of\\n * the retention rate).\\n * @dev In contrast to non-big requests processing, this function will uses to fund\\n * wallet's balance to fill the request. This allows processing requests that are\\n * greater than retention rate without having to exceed this rate on the contract.\\n * @param requestId The ID of the big request to process.\\n */\\n function processBigQueuedRequest(uint256 requestId) external onlyFund whenNotPaused {\\n // Retrieve request data\\n WithdrawalRequest memory request = withdrawalQueue[requestId];\\n\\n // Ensure the request is active\\n require(request.account != address(0), \\\"L66\\\");\\n\\n // Ensure the request emitter has not been blacklisted since request emission\\n require(!isBlacklisted(request.account), \\\"L50\\\");\\n\\n // Ensure this is indeed a big request\\n require(request.amount > getExpectedRetained() / 2, \\\"L51\\\");\\n\\n // Retrieve withdrawal fees and net withdrawn amount\\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\\n request.account,\\n request.amount\\n );\\n\\n // Ensure withdrawn amount can be covered by contract + fund wallet balances\\n uint256 fundBalance = underlying().balanceOf(fund);\\n require(withdrawnAmount <= usableUnderlyings + fundBalance, \\\"L52\\\");\\n\\n // Increase amount of unclaimed fees accordingly\\n unclaimedFees += fees;\\n\\n // Decrease total queued amount by request amount\\n totalQueued -= request.amount;\\n\\n // Increment queue cursor if request was the next request to be processed\\n if (requestId == withdrawalQueueCursor) withdrawalQueueCursor++;\\n\\n // Inform listeners of this queued withdrawal processing activity event\\n emit ActivityEvent(\\n int256(requestId),\\n request.account,\\n Action.Withdraw,\\n request.amount,\\n withdrawnAmount,\\n Status.Success,\\n NO_ID\\n );\\n\\n // Remove request from queue\\n delete withdrawalQueue[requestId];\\n\\n // If fund wallet's balance can cover request, rely on it only\\n if (withdrawnAmount <= fundBalance) {\\n underlying().safeTransferFrom(_msgSender(), request.account, withdrawnAmount);\\n }\\n // Else, cover request from both fund wallet and contract balances\\n else {\\n // Compute amount missing from fund wallet to cover request\\n uint256 missingAmount = withdrawnAmount - fundBalance;\\n\\n // Decrease usable amount of underlying tokens accordingly\\n usableUnderlyings -= missingAmount;\\n\\n // Transfer entire fund balance to request's emitter\\n underlying().safeTransferFrom(_msgSender(), request.account, fundBalance);\\n\\n // Transfer missing amount from contract balance to request emitter\\n underlying().safeTransfer(request.account, missingAmount);\\n }\\n\\n // Transfer exceeding underlying tokens to the fund wallet\\n _transferExceedingToFund();\\n }\\n\\n /**\\n * @notice Cancels a given withdrawal request. The request emitter receive back its\\n * L-Tokens and no fees will be charged.\\n * @param requestId The ID of the withdrawal request to cancel.\\n */\\n function cancelWithdrawalRequest(\\n uint256 requestId\\n ) public whenNotPaused notBlacklisted(_msgSender()) {\\n // Retrieve request data\\n WithdrawalRequest memory request = withdrawalQueue[requestId];\\n\\n // Ensure request belongs to caller\\n require(_msgSender() == request.account, \\\"L57\\\");\\n\\n // Decrease total amount queued accordingly\\n totalQueued -= request.amount;\\n\\n // Delete the withdrawal request from queue\\n delete withdrawalQueue[requestId];\\n\\n // Inform listeners of this cancelled withdrawal request activity event\\n emit ActivityEvent(\\n int256(requestId),\\n request.account,\\n Action.Withdraw,\\n request.amount,\\n request.amount,\\n Status.Cancelled,\\n NO_ID\\n );\\n\\n // Mint back L-Tokens to account\\n _mint(request.account, uint256(request.amount));\\n }\\n\\n /**\\n * @notice Used by the fund wallet to repatriate underlying tokens on the contract\\n * whenever those are required to fulfill some withdrawal requests.\\n * @dev The function will revert if repatriated amount makes the contract exceeding\\n * the retention rate.\\n * @param amount The amount of underlying tokens to repatriate.\\n */\\n function repatriate(uint256 amount) external onlyFund whenNotPaused {\\n // Ensure the fund wallet has enough funds to repatriate\\n require(amount <= underlying().balanceOf(fund), \\\"L58\\\");\\n\\n // Calculate new contract usable balance\\n uint256 newBalance = usableUnderlyings + amount;\\n\\n // Ensure the new balance doesn't exceed the retention rate\\n require(newBalance <= getExpectedRetained(), \\\"L59\\\");\\n\\n // Increase usable underlyings amount by repatriated amount\\n usableUnderlyings += amount;\\n\\n // Transfer amount from fund wallet to contract\\n underlying().safeTransferFrom(_msgSender(), address(this), amount);\\n }\\n\\n /// @notice Used by owner to claim fees generated from successful withdrawals.\\n function claimFees() external onlyOwner {\\n // Ensure there are some fees to claim\\n require(unclaimedFees > 0, \\\"L60\\\");\\n\\n // Ensure the contract holds enough underlying tokens to cover fees\\n require(usableUnderlyings >= unclaimedFees, \\\"L61\\\");\\n\\n // Decrease usable underlyings amount accordingly\\n usableUnderlyings -= unclaimedFees;\\n\\n // Store fees amount in memory and reset unclaimed fees amount\\n uint256 fees = unclaimedFees;\\n unclaimedFees = 0;\\n\\n // Transfer unclaimed fees to owner\\n underlying().safeTransfer(owner(), fees);\\n }\\n}\\n\",\"keccak256\":\"0x8b7b70d1587207f07fe6bbdf47cd3b276646bc7b872f1b2835df0aa2709680a6\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalOwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {OwnableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {GlobalOwner} from \\\"../GlobalOwner.sol\\\";\\n\\n/**\\n * @title GlobalOwnableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\\n * contract (see GlobalOwner.sol). This design facilitates centralized management\\n * of ownership for all the Ledgity Yield contracts.\\n *\\n * @dev Security measure:\\n * The _globalOwner state must be set at initialization time and, for evident security\\n * reasons, cannot be changed afterward.\\n *\\n * @dev For further details, see \\\"GlobalOwnableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\\n /**\\n * @notice The GlobalOwner contract the ownership will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalOwner private _globalOwner;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\\n __GlobalOwnable_init_unchained(globalOwner_);\\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\\n // the initial _owner value, calling it would have no effect.\\n }\\n\\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\\n _globalOwner = GlobalOwner(globalOwner_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalOwner contract.\\n * @return The address of the GlobalOwner contract.\\n */\\n function globalOwner() public view returns (address) {\\n return address(_globalOwner);\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\\n * from the GlobalOwner contract instead.\\n * @return The address of the owner\\n */\\n function owner() public view override returns (address) {\\n return _globalOwner.owner();\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\\n * Ownership is managed by the GlobalOwner contract and must be modified there.\\n */\\n function transferOwnership(address newOwner) public view override onlyOwner {\\n newOwner; // Silence unused variable compiler warning\\n revert(\\\"L8\\\");\\n }\\n\\n /**\\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\\n * Ownership is managed by the GlobalOwner contract and must be modified there.\\n */\\n function renounceOwnership() public view override onlyOwner {\\n revert(\\\"L65\\\");\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x9203f7a2a19def126d8ff0fde8357053ffcf1100d65ec8faec8299b6ed2c0c5a\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalPausableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport {GlobalPause} from \\\"../GlobalPause.sol\\\";\\n\\n/**\\n * @title GlobalPausableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit a pause state from the specified GlobalPause\\n * contract (see GlobalPause.sol). This design facilitates centralized management of\\n * pause state for all the Ledgity Yield contracts.\\n *\\n * @dev Security measure\\n * The _globalPause state must be set at initialization time and, for evident security\\n * reasons, cannot be changed afterward.\\n *\\n * @dev For further details, see \\\"GlobalPausableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\\n /**\\n * @notice The GlobalPause contract the pause state will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalPause private _globalPause;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalPause_ The address of the GlobalPause contract.\\n */\\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\\n __Pausable_init();\\n __GlobalPausable_init_unchained(globalPause_);\\n }\\n\\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\\n _globalPause = GlobalPause(globalPause_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalPause contract.\\n * @return The address of the GlobalPause contract.\\n */\\n function globalPause() public view returns (address) {\\n return address(_globalPause);\\n }\\n\\n /**\\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\\n * from the GlobalPause contract instead.\\n * @return Whether the contract is paused or not.\\n */\\n function paused() public view virtual override returns (bool) {\\n return _globalPause.paused();\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xff508c0b8c48916885453b4894d0401e94580fb24fb6af1885a3e160864cde94\",\"license\":\"MIT\"},\"contracts/src/abstracts/GlobalRestrictableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalBlacklist} from \\\"../GlobalBlacklist.sol\\\";\\n\\n/**\\n * @title GlobalRestrictableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts will inherit a blacklist state from the specified\\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\\n * centralized management of a blacklist for all the Ledgity Yield contracts.\\n *\\n * @dev Security measure:\\n * The _globalBlacklist state must be set at initialization time and, for evident\\n * security reasons, cannot be changed afterward.\\n *\\n * @dev For further details, see \\\"GlobalRestrictableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract GlobalRestrictableUpgradeable is Initializable {\\n /**\\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\\n * @dev This state is private so derived contracts cannot change its value.\\n */\\n GlobalBlacklist private _globalBlacklist;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n */\\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\\n __GlobalRestrictable_init_unchained(globalBlacklist_);\\n }\\n\\n function __GlobalRestrictable_init_unchained(\\n address globalBlacklist_\\n ) internal onlyInitializing {\\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\\n }\\n\\n /**\\n * @notice Retrieves the address of GlobalBlacklist contract.\\n * @return The address of the GlobalBlacklist contract.\\n */\\n function globalBlacklist() public view returns (address) {\\n return address(_globalBlacklist);\\n }\\n\\n /**\\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\\n * @param account Address to verify.\\n */\\n modifier notBlacklisted(address account) {\\n require(isBlacklisted(account) == false, \\\"L9\\\");\\n _;\\n }\\n\\n /**\\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\\n * @param account Address to verify.\\n * @return Whether the account is blacklisted.\\n */\\n function isBlacklisted(address account) internal view returns (bool) {\\n return _globalBlacklist.isBlacklisted(account);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x0032fde90d9cf23e70dd4b604ae0d1ed3283f117bc24f68d32f8933e1bd372bc\",\"license\":\"MIT\"},\"contracts/src/abstracts/InvestUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n// Contracts\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./GlobalOwnableUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"./GlobalPausableUpgradeable.sol\\\";\\nimport {GlobalRestrictableUpgradeable} from \\\"./GlobalRestrictableUpgradeable.sol\\\";\\nimport \\\"./base/BaseUpgradeable.sol\\\";\\nimport {RecoverableUpgradeable} from \\\"../abstracts/RecoverableUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport {APRHistory as APRH} from \\\"../libs/APRHistory.sol\\\";\\nimport {SUD} from \\\"../libs/SUD.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport {IERC20MetadataUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\n\\n/**\\n * @title InvestUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts are provided with utilities to manage an invested token,\\n * users' investment periods, rewards calculations, virtual balances, and auto-compounding.\\n *\\n * @dev Intuition:\\n * This contract primarily exists for code splitting and reusability. It unburdens the\\n * LToken contract code, making it easier to understand and maintain.\\n *\\n * This contract is generic because it may be used in the LDYStaking contract in the future.\\n *\\n * @dev Definitions:\\n * - Investment: The act of depositing or investing tokens into the contract.\\n * - Investment period: Time between the last invested amount change and the present.\\n * - Virtual balance: Temporary storage for account rewards, used when those can't be\\n * distributed between investment periods.\\n * - Rewards redirection: Mechanism allowing an account to redirect its rewards to another.\\n *\\n * @dev Derived contract must:\\n * - Set invested token during initialization\\n * - Implement _investmentOf() function\\n * - (optionally) Implement _distributeRewards() function\\n *\\n * @dev For further details, see \\\"InvestmentUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract InvestUpgradeable is BaseUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n using APRH for APRH.Pack[];\\n\\n /**\\n * @notice Represents an account's investment period.\\n * @param timestamp The timestamp of the most recent rewards distribution.\\n * @param ref The reference of the last APR checkpoint at that timestamp.\\n */\\n struct InvestmentPeriod {\\n uint40 timestamp; // Supports dates up to 20/02/36812\\n APRH.Reference ref;\\n }\\n\\n /**\\n * @notice Represents the investment details of an account.\\n * @param period The current investment period of the account.\\n * @param virtualBalance May hold a part of account rewards until they are claimed.\\n */\\n struct AccountDetails {\\n InvestmentPeriod period;\\n uint256 virtualBalance;\\n }\\n\\n /// @notice Holds a reference to the invested token's contract.\\n IERC20Upgradeable private _invested;\\n\\n /// @notice Holds investment details of each account.\\n mapping(address => AccountDetails) internal accountsDetails;\\n\\n /// @notice Holds an history of the APR value over time (see APRHistory.sol).\\n APRH.Pack[] private _aprHistory;\\n\\n /// @notice Holds active rewards redirections in both from->to and to->from[] ways.\\n mapping(address => address) public rewardsRedirectsFromTo;\\n mapping(address => address[]) public rewardsRedirectsToFrom;\\n\\n /// @notice Is used to prevent infinite loop in _beforeInvestmentChange().\\n bool private _isClaiming;\\n\\n /**\\n * @notice Emitted to inform listeners about a change in the APR's value.\\n * @param newAPRUD7x3 The new APR in UD7x3 format.\\n */\\n event APRChangeEvent(uint16 newAPRUD7x3);\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param invested_ The address of the invested token contract.\\n */\\n function __Invest_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n address invested_\\n ) internal onlyInitializing {\\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\\n __Invest_init_unchained(invested_);\\n }\\n\\n function __Invest_init_unchained(address invested_) internal onlyInitializing {\\n // Set invested token\\n _invested = IERC20Upgradeable(invested_);\\n\\n // Define initial APR to 0%. This would prevent getAPR() from reverting because\\n // of an empty APR history\\n _aprHistory.setAPR(0);\\n }\\n\\n /**\\n * @notice Retrieves the reference to the invested token contract.\\n * @return The reference to the invested token contract.\\n */\\n function invested() public view returns (IERC20Upgradeable) {\\n return _invested;\\n }\\n\\n /**\\n * @notice Updates the investment APR. Restricted to owner.\\n * @param aprUD7x3 The new APR in UD7x3 format.\\n */\\n function setAPR(uint16 aprUD7x3) public onlyOwner {\\n _aprHistory.setAPR(aprUD7x3);\\n emit APRChangeEvent(aprUD7x3);\\n }\\n\\n /**\\n * @notice Retrieves the most recently set APR.\\n * @return The current APR in UD7x3 format.\\n */\\n function getAPR() public view returns (uint16) {\\n return _aprHistory.getAPR();\\n }\\n\\n /**\\n * @notice Enables redirection of rewards from one account to another.\\n * @param from The address of the account to redirect rewards from.\\n * @param to The address of the account to redirect rewards to.\\n */\\n function startRewardsRedirection(\\n address from,\\n address to\\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\\n // Ensure the address is not already redirecting rewards\\n require(rewardsRedirectsFromTo[from] == address(0), \\\"L62\\\");\\n\\n // Ensure neither 'from' nor 'to' are the zero address\\n require(from != address(0), \\\"L12\\\");\\n require(to != address(0), \\\"L13\\\");\\n\\n // Ensure 'from' and 'to' addresses are distinct\\n require(from != to, \\\"L14\\\");\\n\\n // Ensure function caller is either the owner or the 'from' address\\n require(_msgSender() == owner() || _msgSender() == from, \\\"L15\\\");\\n\\n // Distribute current rewards and reset investment periods of both accounts\\n _beforeInvestmentChange(from, true);\\n _beforeInvestmentChange(to, true);\\n\\n // Activate rewards redirection\\n rewardsRedirectsFromTo[from] = to;\\n rewardsRedirectsToFrom[to].push(from);\\n }\\n\\n /**\\n * @notice Disable an active rewards redirection.\\n * @param from The address of the account to stop redirecting rewards from.\\n * @param to The address of the account to stop redirecting rewards to.\\n */\\n function stopRewardsRedirection(\\n address from,\\n address to\\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\\n // Ensure neither 'from' nor 'to' are the zero address\\n require(from != address(0), \\\"L16\\\");\\n require(to != address(0), \\\"L17\\\");\\n\\n // Ensure function caller is either the owner or the 'from' address\\n require(_msgSender() == owner() || _msgSender() == from, \\\"L18\\\");\\n\\n // Ensure a rewards redirection was active\\n require(rewardsRedirectsFromTo[from] == to, \\\"L19\\\");\\n\\n // Distribute current rewards and reset investment periods of both accounts\\n _beforeInvestmentChange(from, true);\\n _beforeInvestmentChange(to, true);\\n\\n // Retrieve 'from' index in the redirection array of 'to'\\n int256 fromIndex = -1;\\n for (uint256 i = 0; i < rewardsRedirectsToFrom[to].length; i++) {\\n if (rewardsRedirectsToFrom[to][i] == from) {\\n fromIndex = int256(i);\\n break;\\n }\\n }\\n\\n // fromIndex should never be -1 at this point\\n assert(fromIndex >= 0);\\n\\n // Deactivate rewards redirection\\n rewardsRedirectsFromTo[from] = address(0);\\n rewardsRedirectsToFrom[to][uint256(fromIndex)] = rewardsRedirectsToFrom[to][\\n rewardsRedirectsToFrom[to].length - 1\\n ];\\n rewardsRedirectsToFrom[to].pop();\\n }\\n\\n /**\\n * @notice Retrieves the total amount of tokens invested by the given account.\\n * @dev Derived contracts must implement this function.\\n * @param account The account to get the investment of.\\n * @return The total amount of tokens invested by the given account.\\n */\\n function _investmentOf(address account) internal view virtual returns (uint256);\\n\\n /**\\n * @notice Distributes a specified amount of rewards to a given account.\\n * @dev Derived contracts may optionally implement this function.\\n * @dev Implementations must return true to indicate a successful distribution, and\\n * false otherwise. If it returns false, the rewards will be added to the account's\\n * virtual balance, in order to be claimed later.\\n * @param account The account to claim the rewards of.\\n * @param amount The amount of rewards to claim.\\n * @return Whether the rewards distribution was successfull.\\n */\\n function _distributeRewards(address account, uint256 amount) internal virtual returns (bool) {\\n account; // Silence unused variables warning\\n amount;\\n return false;\\n }\\n\\n /**\\n * @notice Computes the rewards accrued over a specified period of time, based on a\\n * given APR and amount of invested tokens.\\n * @dev For further details, see \\\"InvestUpgradeable > Rewards calculation\\\" section of\\n * the whitepaper.\\n * @param beginTimestamp The moment the period commenced.\\n * @param endTimestamp The moment the period concluded.\\n * @param aprUD7x3 The APR during this period, in UD7x3 format.\\n * @param investedAmount The amount of tokens deposited/invested during the period.\\n * @return The amount of rewards generated during the period.\\n */\\n function _calculatePeriodRewards(\\n uint40 beginTimestamp,\\n uint40 endTimestamp,\\n uint16 aprUD7x3,\\n uint256 investedAmount\\n ) internal view returns (uint256) {\\n // Cache invested token's decimals number\\n uint256 d = SUD.decimalsOf(address(invested()));\\n\\n // Compute the number of elapsed years\\n uint256 elapsedTimeSUD = SUD.fromInt(endTimestamp - beginTimestamp, d);\\n uint256 elapsedYearsSUD = (elapsedTimeSUD * SUD.fromInt(1, d)) / SUD.fromInt(365 days, d);\\n\\n // Compute the growth in invested amount (thanks to rewards)\\n uint256 aprSUD = SUD.fromRate(aprUD7x3, d);\\n uint256 growthSUD = (elapsedYearsSUD * aprSUD) / SUD.fromInt(1, d);\\n\\n // Compute and return the rewards\\n uint256 investedAmountSUD = SUD.fromAmount(investedAmount, d);\\n uint256 rewardsSUD = (investedAmountSUD * growthSUD) / SUD.fromInt(100, d);\\n return SUD.toAmount(rewardsSUD, d);\\n }\\n\\n /**\\n * @notice Computes the sum of given account's invested amount, plus invested amount\\n * of all accounts that recursively redirect rewards to this account.\\n * @param account The account to calculate the deep investment of.\\n * @return deepInvestedAmount The deep invested amount.\\n */\\n function _deepInvestmentOf(address account) internal view returns (uint256 deepInvestedAmount) {\\n // Consider account's direct investment\\n deepInvestedAmount += _investmentOf(account);\\n\\n // But also the deep investments of all accounts redirecting rewards to this account\\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\\n deepInvestedAmount += _deepInvestmentOf(rewardsRedirectsToFrom[account][i]);\\n }\\n }\\n\\n /**\\n * @notice Computes the amount of unclaimed/undistributed rewards of a given account.\\n * @dev For further details, see \\\"InvestUpgradeable > Rewards calculation\\\" section of\\n * the whitepaper.\\n * @param account The account to calculate the unclaimed rewards of.\\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\\n * @return rewards The amount of unclaimed/undistributed rewards of the given account.\\n */\\n function _rewardsOf(\\n address account,\\n bool autocompound\\n ) internal view returns (uint256 rewards) {\\n // Retrieve account's investment details\\n AccountDetails memory details = accountsDetails[account];\\n\\n // Retrieve account's deep invested amount\\n uint256 investedAmount = _deepInvestmentOf(account);\\n\\n // Return 0 if the account has never invested or has no invested amount\\n if (details.period.timestamp == 0 || investedAmount == 0) return 0;\\n\\n // Retrieve reference and data of APR checkpoint at which started investment period\\n APRH.Reference memory currRef = details.period.ref;\\n APRH.CheckpointData memory currCheckpoint = _aprHistory.getDataFromReference(currRef);\\n\\n // Retrieve reference of latest APR checkpoint\\n APRH.Reference memory latestRef = _aprHistory.getLatestReference();\\n\\n // 1) Fill rewards with virtual balance (rewards not claimed/distributed yet)\\n // See \\\"InvestUpgradeable > Yield calculation > 1)\\\" section of the whitepaper\\n rewards = details.virtualBalance;\\n\\n // If start checkpoint is not the latest one\\n if (!APRH.eq(currRef, latestRef)) {\\n // Retrieve reference and data of APR checkpoint that comes after start checkpoint\\n APRH.Reference memory nextRef = APRH.incrementReference(currRef);\\n APRH.CheckpointData memory nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\\n\\n // 2) Calculate rewards from investment period start to next checkpoint\\n // See \\\"InvestUpgradeable > Yield calculation > 2)\\\" section of the whitepaper\\n rewards += _calculatePeriodRewards(\\n details.period.timestamp,\\n nextCheckpoint.timestamp,\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n\\n // 3) Calculate rewards for each crossed pair of checkpoints\\n // See \\\"InvestUpgradeable > Yield calculation > 3)\\\" section of the whitepaper\\n while (true) {\\n // Set next checkpoint as the current one\\n currRef = nextRef;\\n currCheckpoint = nextCheckpoint;\\n\\n // Break if current checkpoint is the latest one\\n if (APRH.eq(currRef, latestRef)) break;\\n\\n // Else, retrieve the new next checkpoint\\n nextRef = APRH.incrementReference(currRef);\\n nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\\n\\n // Calculate rewards between the current pair of checkpoints\\n rewards += _calculatePeriodRewards(\\n currCheckpoint.timestamp,\\n nextCheckpoint.timestamp,\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n }\\n\\n // 4) Calculate rewards from the latest checkpoint to now\\n // See \\\"InvestUpgradeable > Yield calculation > 4)\\\" section of the whitepaper\\n rewards += _calculatePeriodRewards(\\n currCheckpoint.timestamp,\\n uint40(block.timestamp),\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n } else {\\n // 2.bis) Calculate rewards from investment period start to now\\n // See \\\"InvestUpgradeable > Yield calculation > 2.bis)\\\" section of the whitepaper\\n rewards += _calculatePeriodRewards(\\n details.period.timestamp,\\n uint40(block.timestamp),\\n currCheckpoint.aprUD7x3,\\n investedAmount + (autocompound ? rewards : 0)\\n );\\n }\\n }\\n\\n /**\\n * @notice Recursively resets the investment period of the specified account and of\\n * all accounts that directly or indirectly redirect rewards to this account.\\n * @param account The account to deeply reset the investment period of.\\n */\\n function _deepResetInvestmentPeriodOf(address account) internal {\\n // Reset account investment period timestamp and APR checkpoint to latest ones\\n accountsDetails[account].period.timestamp = uint40(block.timestamp);\\n accountsDetails[account].period.ref = _aprHistory.getLatestReference();\\n\\n // Also reset the ones of all accounts that recursively redirect rewards to this account\\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\\n _deepResetInvestmentPeriodOf(rewardsRedirectsToFrom[account][i]);\\n }\\n }\\n\\n /**\\n * @notice Hook to be invoked before the invested amount of an account changes. It\\n * ensures that rewards are distributed and that account's investment period is reset.\\n * @param account The account whose invested amount is going to change.\\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\\n */\\n function _beforeInvestmentChange(address account, bool autocompound) internal {\\n // This hook is called inside LToken._beforeTokenTransfer() and as new tokens are\\n // minted in LToken._distributeRewards(), this guards against infinite loop.\\n if (_isClaiming) return;\\n\\n // LToken._beforeTokenTransfer() calls this hook for both involved addresses.\\n // As first call will treat both addresses, the second call would be redundant.\\n // Therefore, we skip accounts already processed in this block to save up some gas.\\n if (accountsDetails[account].period.timestamp == uint40(block.timestamp)) return;\\n\\n // If account redirects its rewards\\n address redirectRewardsTo = rewardsRedirectsFromTo[account];\\n if (redirectRewardsTo != address(0)) {\\n // Call hook on redirection target (this will indirectly reset the investment\\n // of this source account) and return\\n _beforeInvestmentChange(redirectRewardsTo, autocompound);\\n return;\\n }\\n\\n // Else, compute account's undistributed/unclaimed rewards\\n uint256 rewards = _rewardsOf(account, autocompound);\\n\\n // If there are some rewards\\n if (rewards > 0) {\\n // Try to distribute rewards to account\\n _isClaiming = true;\\n bool distributed = _distributeRewards(account, rewards);\\n _isClaiming = false;\\n\\n // If rewards have not been distributed, accumulate them in account's virtual balance\\n if (!distributed) accountsDetails[account].virtualBalance = rewards;\\n }\\n\\n // Finally, deeply reset investment period of the account\\n _deepResetInvestmentPeriodOf(account);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xdb6d0b0e2f2546b6be0ac9244e99017c5e5da1e5b7783d6fff50f4217b9ec820\",\"license\":\"MIT\"},\"contracts/src/abstracts/RecoverableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n// Conracts\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"./GlobalOwnableUpgradeable.sol\\\";\\n\\n// Libraries\\nimport {SafeERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\n// Interfaces\\nimport {IERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @title RecoverableUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice Derived contracts are provided with helper functions allowing the recovery of\\n * assets accidentally sent to them.\\n *\\n * @dev Where are utilities Ether, ERC721, etc.?\\n * This abstract contract currently supports only ERC20 tokens. Derived contracts\\n * in this codebase currently do not implement the necessary functions to receive Ether\\n * or ERC721/ERC1155 tokens, so no recovery functions are provided for these assets.\\n *\\n * @dev For further details, see \\\"RecoverableUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n */\\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\\n __GlobalOwnable_init(globalOwner_);\\n __Recoverable_init_unchained();\\n }\\n\\n function __Recoverable_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Recovers a specified amount of a given token address. Will fail if the\\n * contract doesn't hold enough tokens.\\n * @param tokenAddress The address of the token to recover.\\n * @param amount The amount of token to recover.\\n */\\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\\n // Ensure the specified amount is not zero\\n require(amount > 0, \\\"L10\\\");\\n\\n // Create a reference to token's contract\\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\\n\\n // Ensure there is enough token to recover\\n require(tokenContract.balanceOf(address(this)) >= amount, \\\"L11\\\");\\n\\n // Transfer the recovered token amount to the sender\\n tokenContract.safeTransfer(_msgSender(), amount);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xc70110d1284c9e4aa7c518b3b98682dd9edbe6f6fb23761d825554ba41a80d5e\",\"license\":\"MIT\"},\"contracts/src/abstracts/base/BaseUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"../GlobalPausableUpgradeable.sol\\\";\\nimport {GlobalOwnableUpgradeable} from \\\"../GlobalOwnableUpgradeable.sol\\\";\\nimport {GlobalRestrictableUpgradeable} from \\\"../GlobalRestrictableUpgradeable.sol\\\";\\nimport {RecoverableUpgradeable} from \\\"../RecoverableUpgradeable.sol\\\";\\n\\n/**\\n * @title BaseUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This abstract contract acts as a base for numerous contracts in this codebase,\\n * minimizing code repetition and enhancing readability and maintainability.\\n *\\n * @dev For further details, see \\\"Base\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract BaseUpgradeable is\\n Initializable,\\n UUPSUpgradeable,\\n GlobalOwnableUpgradeable,\\n GlobalPausableUpgradeable,\\n GlobalRestrictableUpgradeable,\\n RecoverableUpgradeable\\n{\\n /**\\n * @notice Prevents implementation contract from being initialized as recommended by\\n * OpenZeppelin.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n */\\n function __Base_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_\\n ) internal onlyInitializing {\\n __UUPSUpgradeable_init();\\n __GlobalOwnable_init(globalOwner_);\\n __Pausable_init();\\n __GlobalPausable_init_unchained(globalPause_);\\n __GlobalRestrictable_init_unchained(globalBlacklist_);\\n __Recoverable_init_unchained();\\n }\\n\\n function __Base_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\\n * global owner. It is called by the proxy contract during an upgrade.\\n * @param newImplementation The address of the new implementation contract.\\n */\\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xe445c759682f31d39e63663ff8217072c0e81086bda11ea473247be334c3e424\",\"license\":\"MIT\"},\"contracts/src/abstracts/base/ERC20BaseUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {ERC20Upgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\\\";\\nimport {ERC20PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\\\";\\nimport {PausableUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\\\";\\nimport \\\"./BaseUpgradeable.sol\\\";\\nimport {GlobalPausableUpgradeable} from \\\"../GlobalPausableUpgradeable.sol\\\";\\n\\n/**\\n * @title ERC20BaseUpgradeable\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This abstract contract is an extension of BaseUpgradeable intended to be used\\n * as a base for ERC20 tokens contracts.\\n *\\n * @dev For further details, see \\\"ERC20BaseUpgradeable\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nabstract contract ERC20BaseUpgradeable is\\n ERC20Upgradeable,\\n BaseUpgradeable,\\n ERC20PausableUpgradeable\\n{\\n /**\\n * @notice Initializer functions of the contract. They replace the constructor()\\n * function in the context of upgradeable contracts.\\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\\n * @param globalOwner_ The address of the GlobalOwner contract.\\n * @param globalPause_ The address of the GlobalPause contract.\\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\\n * @param name_ The display name of the token.\\n * @param symbol_ The symbol of the token.\\n */\\n function __ERC20Base_init(\\n address globalOwner_,\\n address globalPause_,\\n address globalBlacklist_,\\n string memory name_,\\n string memory symbol_\\n ) internal onlyInitializing {\\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\\n __ERC20_init(name_, symbol_);\\n __ERC20Pausable_init_unchained();\\n }\\n\\n function __ERC20Base_init_unchained() internal onlyInitializing {}\\n\\n /**\\n * @notice Required override of paused() which is implemented by both\\n * GlobalPausableUpgradeable and PausableUpgradeable parent contracts.\\n * The GlobalPausableUpgradeable version is preferred because it checks the pause\\n * state from the GlobalPause contract.\\n * @inheritdoc GlobalPausableUpgradeable\\n */\\n function paused()\\n public\\n view\\n virtual\\n override(GlobalPausableUpgradeable, PausableUpgradeable)\\n returns (bool)\\n {\\n return GlobalPausableUpgradeable.paused();\\n }\\n\\n /**\\n * @dev Required override of _beforeTokenTransfer() which is implemented by both\\n * ERC20PausableUpgradeable and ERC20Upgradeable parent contracts.\\n * The ERC20PausableUpgradeable version is preferred because it also checks that\\n * the contract is not paused before allowing the transfer.\\n * @inheritdoc ERC20PausableUpgradeable\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n )\\n internal\\n virtual\\n override(ERC20PausableUpgradeable, ERC20Upgradeable)\\n whenNotPaused\\n notBlacklisted(from)\\n notBlacklisted(to)\\n {\\n ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);\\n }\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add\\n * new variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xa69b9acca2902fcfe513889516fcffc830903fc3c6a3a11e2ad8da7460201378\",\"license\":\"MIT\"},\"contracts/src/interfaces/ITransfersListener.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\ninterface ITransfersListener {\\n function onLTokenTransfer(address from, address to, uint256 amount) external;\\n}\\n\",\"keccak256\":\"0xf1d4172da97ccaf7199601dd9bdb2ac92a49b6977ec34bba010af37f662549fb\",\"license\":\"MIT\"},\"contracts/src/libs/APRHistory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n/**\\n * @title APRHistory\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice This library offers utilities to efficiently maintain the history of an\\n * on-chain APR (Annual Percentage Rate) state. Each entry in this history is called\\n * a \\\"checkpoint\\\".\\n *\\n * @dev Intuition:\\n * Each checkpoint in an APR history consists of two data:\\n * - the creation timestamp\\n * - the APR at that time\\n *\\n * Given that reading and writing to storage slots are among the most costly operations\\n * in Solidity, this library provides a way to store those data in a way that minimizes\\n * the number of used storage slots.\\n *\\n * Instead of storing each checkpoint in a separate storage slot, this library\\n * facilitates the packing of up to 4 checkpoints in a single storage slot.\\n *\\n * @dev Definitions:\\n * - Checkpoint: A record of an APR change\\n * - Pack: A collection of 4 checkpoints stored in a single storage slot\\n * - History: A dynamic array of packs\\n * - Reference: A storage pointer to a checkpoint in the APR history\\n * - CheckpointData: An in-memory representation of a checkpoint data\\n *\\n * @dev Value limitation:\\n * This library can accommodate APRs only up to 65.536%. This is however sufficient for\\n * APR in LToken contract, which is expected to remain below 10%.\\n *\\n * @dev For further details, see \\\"APRHistory\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nlibrary APRHistory {\\n /**\\n * @notice Represents data of a checkpoint extracted from the on-chain history.\\n * For on-chain representation see \\\"Pack\\\" struct.\\n * @param aprUD7x3 APR in UD7x3 format (e.g., 12345 = 12.345%).\\n * @param timestamp Timestamp of the checkpoint's creation.\\n */\\n struct CheckpointData {\\n uint16 aprUD7x3; // Allows up to 65.536%\\n uint40 timestamp; // Supports dates up to 20/02/36812\\n }\\n\\n /**\\n * @notice Represents how APR checkpoints are stored on chain. Each pack can contain\\n * the data 4 checkpoints. Packs are then stored in a dynamic array (the history).\\n * @param aprsUD7x3 Array of checkpoints' APRs.\\n * @param timestamps Array of checkpoints' timestamps.\\n * @param cursor Index of the next checkpoint to be written.\\n */\\n struct Pack {\\n uint16[4] aprsUD7x3;\\n uint40[4] timestamps;\\n uint32 cursor;\\n }\\n\\n /**\\n * @notice Represents a storage pointer to a specific checkpoint in the history.\\n * @param packIndex Index of the pack the checkpoint belongs to.\\n * @param cursorIndex Index of the checkpoint in this pack (between 0 and 3).\\n */\\n struct Reference {\\n uint256 packIndex;\\n uint32 cursorIndex;\\n }\\n\\n /**\\n * @notice Compares two checkpoints references.\\n * @param ref1 The first reference to compare.\\n * @param ref2 The second reference to compare.\\n * @return Whether the two references points to the same checkpoint.\\n */\\n function eq(Reference memory ref1, Reference memory ref2) external pure returns (bool) {\\n return ref1.packIndex == ref2.packIndex && ref1.cursorIndex == ref2.cursorIndex;\\n }\\n\\n /**\\n * @notice Returns the reference of the checkpoint that should come right after the\\n * referenced checkpoint in the APR history.\\n * @param ref The reference to be incremented.\\n * @return The incremented reference.\\n */\\n function incrementReference(Reference memory ref) public pure returns (Reference memory) {\\n // Ensure cursor index of the given ref is within valid range [0, 3]\\n require(ref.cursorIndex <= 3, \\\"L1\\\");\\n\\n // If the given ref is the last slot in its pack, return ref of next pack's first slot\\n if (ref.cursorIndex == 3) return Reference(ref.packIndex + 1, 0);\\n //\\n // Else, return ref of next slot in current pack\\n else return Reference(ref.packIndex, ref.cursorIndex + 1);\\n }\\n\\n /**\\n * @notice Extracts checkpoint data from a given reference and in APR history.\\n * @param self The APR history to extract the checkpoint from.\\n * @param ref The reference of the checkpoint data to extract.\\n * @return The extracted checkpoint's data.\\n */\\n function getDataFromReference(\\n Pack[] storage self,\\n Reference memory ref\\n ) public view returns (CheckpointData memory) {\\n // Ensure cursor index of the given ref is within valid range [0, 3]\\n require(ref.cursorIndex <= 3, \\\"L2\\\");\\n\\n // Ensure pack index of the given ref exists in history\\n require(ref.packIndex < self.length, \\\"L3\\\");\\n\\n // Retrieve pack data from history\\n Pack memory pack = self[ref.packIndex];\\n\\n // Ensure cursor index of the given ref has been written\\n require(ref.cursorIndex < pack.cursor, \\\"L4\\\");\\n\\n // Build and return the checkpoint data\\n return\\n CheckpointData({\\n aprUD7x3: pack.aprsUD7x3[ref.cursorIndex],\\n timestamp: pack.timestamps[ref.cursorIndex]\\n });\\n }\\n\\n /**\\n * @notice Retrieves the reference to the most recently added checkpoint in the APR history.\\n * @param self The history to extract the reference from.\\n * @return The reference of the latest checkpoint.\\n */\\n function getLatestReference(Pack[] storage self) public view returns (Reference memory) {\\n // Ensure the given history is not empty\\n require(self.length != 0, \\\"L5\\\");\\n\\n // Retrieve latest pack's index and cursor\\n uint256 packIndex = self.length - 1;\\n uint32 packCursor = self[packIndex].cursor;\\n\\n // If this is the first pack ever, ensure it is not empty\\n if (packIndex == 0) require(packCursor != 0, \\\"L6\\\");\\n\\n // If the pack is empty, return ref of previous pack's latest slot\\n if (packCursor == 0) return Reference(packIndex - 1, 3);\\n //\\n // Else, return ref of previous slot in current pack\\n else return Reference(packIndex, packCursor - 1);\\n }\\n\\n /**\\n * @notice Appends a new empty pack to the end of the given APR history array.\\n * @param self The APR history to append an empty to.\\n */\\n function newBlankPack(Pack[] storage self) internal {\\n // If history is not empty, ensure the latest pack is full\\n require(self.length == 0 || getLatestReference(self).cursorIndex == 3, \\\"L7\\\");\\n\\n // Push a new blank pack to the history array\\n self.push(\\n Pack({\\n aprsUD7x3: [uint16(0), uint16(0), uint16(0), uint16(0)],\\n timestamps: [uint40(0), uint40(0), uint40(0), uint40(0)],\\n cursor: 0\\n })\\n );\\n }\\n\\n /**\\n * @notice Write a new APR checkpoint at the end of the given history array.\\n * @param self The array of packs to write the new checkpoint to.\\n * @param aprUD7x3 The new APR in UD7x3 format.\\n */\\n function setAPR(Pack[] storage self, uint16 aprUD7x3) external {\\n // Determine the reference where the new checkpoint should be written\\n Reference memory newRef = self.length == 0\\n ? Reference(0, 0)\\n : incrementReference(getLatestReference(self));\\n\\n // If pack to be written doesn't exist yet, push a new blank pack in history\\n if (newRef.packIndex >= self.length) newBlankPack(self);\\n\\n // Retrieve the pack where the new checkpoint will be stored\\n Pack memory pack = self[newRef.packIndex];\\n\\n // Add new checkpoint's data to the pack\\n pack.aprsUD7x3[newRef.cursorIndex] = aprUD7x3;\\n pack.timestamps[newRef.cursorIndex] = uint40(block.timestamp);\\n\\n // Increment the pack's cursor\\n pack.cursor++;\\n\\n // Write the updated pack in storage\\n self[newRef.packIndex] = pack;\\n }\\n\\n /**\\n * @notice Retrieves the APR of the latest checkpoint written in the APR history.\\n * @param self The history array to read APR from.\\n * @return The latest checkpoint's APR.\\n */\\n function getAPR(Pack[] storage self) public view returns (uint16) {\\n // Retrieve the latest checkpoint data\\n Reference memory ref = getLatestReference(self);\\n CheckpointData memory data = getDataFromReference(self, ref);\\n\\n // Return the latest checkpoint's APR\\n return data.aprUD7x3;\\n }\\n}\\n\",\"keccak256\":\"0x0b3d02a33c5e5be03cefc5192439def2efa43be664c372e83f309be34fd476b7\",\"license\":\"MIT\"},\"contracts/src/libs/SUD.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\nimport {IERC20MetadataUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\n\\n/**\\n * @title SUD\\n * @author Lila Rest (https://lila.rest)\\n * @custom:security-contact security@ledgity.com\\n *\\n * @notice SUD serves as an intermediary number format for calculations within this\\n * codebase. It ensures consistency and reduces precision losses. This library\\n * facilitates conversions between various number formats and the SUD format.\\n *\\n * @dev Intuition:\\n * This codebase employs the UD (unsigned decimal fixed-point numbers) format to\\n * represent both percentage rates and tokens amounts.\\n *\\n * Rates are expressed in UD7x3 format, whereas the format for tokens amounts depends on\\n * the decimals() value of the involved tokens.\\n *\\n * Three challenges arise from this:\\n * 1) To compute values together, it's essential that they are in the same format\\n * 2) Calculations involving consecutive divisions on UD numbers lead to accumulated\\n * precision loss (because division shrinks). A common approach is to scale up and\\n * down values by a few decimals before and after performing calculations.\\n * 3) Given that rates use the UD7x3 format, if we decided to scale them to and from\\n * the number of decimals of the involved token, 1 to 3 of the rates' decimals would\\n * be shrunk in case token's decimals number is in [0, 2].\\n *\\n * To address these challenges, this library provides the SUD format, which acts as a\\n * consistent and scaled intermediate format to perform calculations.\\n *\\n * SUD is an acronym for either \\\"Scaled UD\\\" or \\\"Safe UD\\\".\\n *\\n * @dev Definitions:\\n * - Integer: A number without fractional part, e.g., block.timestamp\\n * - UD: A decimal unsigned fixed-point number. The \\\"UD\\\" notation is inspired from\\n * libraries like [prb-math](https://github.com/PaulRBerg/prb-math/)\\n * - Amount: A token amount. A UD with an unknown repartition of digits between integral\\n * and fractional parts (as token amounts have variable decimal numbers)\\n * - Rate: A percentage rate. An UD with 7 integral digits and 3 fractional ones (= UD7x3)\\n * - SUD: An intermediate format to perform calculations involving Rates and Amounts. A UD\\n * with 3 more decimals than the involved UD with the highest decimals number. As\\n * rates are represented by UD7x3, a SUD number has at least 6 decimals (3+3) and\\n * so ranges from UD71x6 to UD0x77 formats.\\n *\\n * @dev A conversion library:\\n * This library provides utilities to perform the following conversions:\\n * - Amount <--> SUD\\n * - Rate (UD7x3) <--> SUD\\n * - Integer <--> SUD\\n *\\n * @dev Why scaling by 3 decimals?\\n * - It provides an adequate degree of precision for this codebase,\\n * - It enables the conversion of a UD7x3 rate to SUD format by merely scaling it up by\\n * the involved token's decimal number, so is gas efficient.\\n *\\n * @dev Why internal functions?\\n * The functions of this library are not set to external because incorporating them\\n * directly into contracts is more gas-efficient. Given their minimal size and frequent\\n * usage in the InvestUpgradeable, LDYStaking, and LToken contracts, any bytecode savings\\n * from making them external are negated by the additional bytecode required for external\\n * calls to this library. This can be observed by comparing the output of `bun cc:size`\\n * when those functions's visibility is set to external or internal.\\n *\\n * @dev Precision warning:\\n * While this library mitigates precision loss during calculations on UD numbers, it's\\n * important to note that tokens with lower decimal counts and supply inherently suffer\\n * more from precision loss. Conversely, tokens with higher decimal counts and supply\\n * will experience less precision loss.\\n *\\n * @dev For further details, see \\\"SUD\\\" section of whitepaper.\\n * @custom:security-contact security@ledgity.com\\n */\\nlibrary SUD {\\n /**\\n * @notice Retrieves decimals number of the given ERC20 contract address.\\n * @param tokenAddress The address to retrieve decimals number from.\\n * @return decimals The decimals number of the given ERC20 contract address.\\n */\\n function decimalsOf(address tokenAddress) internal view returns (uint256 decimals) {\\n return IERC20MetadataUpgradeable(tokenAddress).decimals();\\n }\\n\\n /**\\n * @notice Convert a given token amount into SUD format.\\n * @param nAmount The token amount to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nSUD The amount in SUD format\\n */\\n function fromAmount(uint256 nAmount, uint256 decimals) internal pure returns (uint256 nSUD) {\\n // If token decimals < 3, return a UD71x6 number\\n if (decimals < 3) return nAmount * 10 ** (6 - decimals);\\n\\n // Else return a number with decimals+3 fractional digits\\n return nAmount * 10 ** 3;\\n }\\n\\n /**\\n * @notice Convert a given SUD number into token amount format.\\n * @param nSUD The SUD number to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nAmount The number in amount format\\n */\\n function toAmount(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nAmount) {\\n // If token decimals < 3, convert from a UD71x6 number\\n if (decimals < 3) return nSUD / 10 ** (6 - decimals);\\n\\n // Else, convert from a number with decimals+3 fractional digits\\n return nSUD / 10 ** 3;\\n }\\n\\n /**\\n * @notice Converts a given UD7x3 rate into SUD format.\\n * @param nUD7x3 The UD7x3 rate to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nSUD The rate in SUD format.\\n */\\n function fromRate(uint256 nUD7x3, uint256 decimals) internal pure returns (uint256 nSUD) {\\n // If token decimals < 3, return a UD71x6 number\\n if (decimals < 3) return nUD7x3 * 10 ** 3;\\n\\n // Else, return a number with decimals+3 fractional digits\\n return nUD7x3 * 10 ** decimals;\\n }\\n\\n /**\\n * @notice Converts a given SUD number into a UD7x3 rate.\\n * @param nSUD The SUD number to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nUD7x3 The number in UD7x3 rate format.\\n */\\n function toRate(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nUD7x3) {\\n // If token decimals < 3, convert from a UD71x6 number\\n if (decimals < 3) return nSUD / 10 ** 3;\\n\\n // Else, convert from a number with decimals+3 fractional digits\\n return nSUD / 10 ** decimals;\\n }\\n\\n /**\\n * @notice Converts a given integer into SUD format.\\n * @param n The integer to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return nSUD The integer in SUD format.\\n */\\n function fromInt(uint256 n, uint256 decimals) internal pure returns (uint256 nSUD) {\\n // If token decimals < 3, return a UD71x6 number\\n if (decimals < 3) return n * 10 ** 6;\\n\\n // Else, return a number with decimals+3 fractional digits\\n return n * 10 ** (decimals + 3);\\n }\\n\\n /**\\n * @notice Converts a given SUD number as an integer (all decimals shrinked).\\n * @param nSUD The SUD number to convert.\\n * @param decimals The decimals number of the involved ERC20 token.\\n * @return n The SUD number as an integer.\\n */\\n function toInt(uint256 nSUD, uint256 decimals) internal pure returns (uint256 n) {\\n // If token decimals < 3, convert from a UD71x6 number\\n if (decimals < 3) return nSUD / 10 ** 6;\\n\\n // Else, convert from a number with decimals+3 fractional digits\\n return nSUD / 10 ** (decimals + 3);\\n }\\n}\\n\",\"keccak256\":\"0x7297fc67064b5925e26fa5ed3a4ba4b0f64a9162fdf0ebc2aac8649fddce543a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e7565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e5576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615ee96200011f6000396000818161141b0152818161145b01528181611894015281816118d401526119500152615ee96000f3fe60806040526004361061036f5760003560e01c80638980f11f116101c8578063c822adda116100f8578063dd62ed3e1161009b578063dd62ed3e14610ac9578063ee1335d114610ae9578063ee153c4f14610b09578063ef2591af14610b29578063ef356a7914610b4e578063f12d54d814610b63578063f2fde38b14610b82578063f762e73414610ba2578063f94ce2c214610bc157600080fd5b8063c822adda146109bd578063c89d5b8b146109dd578063cafb220214610a05578063cdc1842414610a24578063d038875c14610a45578063d039981b14610a7f578063d294f09314610a9f578063db84faac14610ab457600080fd5b80639f79b1c61161016b5780639f79b1c614610892578063a457c2d7146108b2578063a64c91cc146108d2578063a8f76320146108f2578063a9059cbb14610912578063b2de2a4314610932578063b60d428814610947578063b6b55f2514610968578063bacd609e1461098857600080fd5b80638980f11f1461079e5780638d8e6bd7146107be5780638da5cb5b146107f557806392e5ced71461080a57806395d89b411461082a57806399a03c701461083f5780639c2719751461085f5780639ee679e81461087f57600080fd5b80634134bee9116102a35780636d3a4ac8116102465780636d3a4ac8146106a75780636f307dc3146106c757806370a08231146106dc578063715018a6146106fc578063734d8287146107115780637594d0b51461072857806375a5652b1461073f5780637c2edb161461075f5780638370e1f71461077e57600080fd5b80634134bee9146105ac57806345b05d09146105cc5780634f1ef286146105ec57806352d1902d146105ff57806353ac4b661461061457806353d3a42f1461062b5780635c975abb146106725780635f0e8e371461068757600080fd5b806323b872dd1161031657806323b872dd1461048b5780632a1b8b1c146104ab5780632f4f21e2146104c0578063313ce567146104e05780633659cfe614610507578063391d85ec1461052757806339509351146105555780633e7ae353146105755780633fd52fb91461059557600080fd5b806306fdde0314610374578063095ea7b31461039f5780630d174c24146103cf5780630e21750f146103f15780631459457a1461041157806318160ddd146104315780631c19be6d14610454578063205c28781461046b575b600080fd5b34801561038057600080fd5b50610389610be1565b6040516103969190615364565b60405180910390f35b3480156103ab57600080fd5b506103bf6103ba3660046153ac565b610c73565b6040519015158152602001610396565b3480156103db57600080fd5b506103ef6103ea3660046153d8565b610c8d565b005b3480156103fd57600080fd5b506103ef61040c3660046153d8565b610cf9565b34801561041d57600080fd5b506103ef61042c3660046153f5565b610d60565b34801561043d57600080fd5b50610446610fd0565b604051908152602001610396565b34801561046057600080fd5b506104466102fe5481565b34801561047757600080fd5b506103bf6104863660046153ac565b610ffb565b34801561049757600080fd5b506103bf6104a6366004615466565b61102c565b3480156104b757600080fd5b506103ef611052565b3480156104cc57600080fd5b506103bf6104db3660046153ac565b6113d6565b3480156104ec57600080fd5b506104f5611407565b60405160ff9091168152602001610396565b34801561051357600080fd5b506103ef6105223660046153d8565b611411565b34801561053357600080fd5b506102f954610548906001600160a01b031681565b60405161039691906154a7565b34801561056157600080fd5b506103bf6105703660046153ac565b6114d9565b34801561058157600080fd5b506105486105903660046153ac565b6114fb565b3480156105a157600080fd5b506104466103035481565b3480156105b857600080fd5b506103ef6105c73660046154bb565b611534565b3480156105d857600080fd5b506103ef6105e73660046154bb565b61171d565b6103ef6105fa36600461556c565b61188a565b34801561060b57600080fd5b50610446611943565b34801561062057600080fd5b506104466102fd5481565b34801561063757600080fd5b5061064b6106463660046154bb565b6119f1565b604080516001600160a01b0390931683526001600160601b03909116602083015201610396565b34801561067e57600080fd5b506103bf611a2d565b34801561069357600080fd5b506103ef6106a23660046153d8565b611a37565b3480156106b357600080fd5b506103ef6106c236600461560f565b611b8e565b3480156106d357600080fd5b50610548611c3f565b3480156106e857600080fd5b506104466106f73660046153d8565b611c4f565b34801561070857600080fd5b506103ef611c6d565b34801561071d57600080fd5b506104466102fc5481565b34801561073457600080fd5b506104466103005481565b34801561074b57600080fd5b506103ef61075a3660046154bb565b611ca3565b34801561076b57600080fd5b50610193546001600160a01b0316610548565b34801561078a57600080fd5b506103ef6107993660046154bb565b612022565b3480156107aa57600080fd5b506103ef6107b93660046153ac565b612185565b3480156107ca57600080fd5b506105486107d93660046153d8565b610291602052600090815260409020546001600160a01b031681565b34801561080157600080fd5b506105486121e5565b34801561081657600080fd5b506103ef61082536600461562c565b612254565b34801561083657600080fd5b5061038961248b565b34801561084b57600080fd5b5061044661085a3660046153d8565b61249a565b34801561086b57600080fd5b506103ef61087a3660046153d8565b6124b8565b6103ef61088d3660046154bb565b612513565b34801561089e57600080fd5b506103ef6108ad3660046154bb565b61286b565b3480156108be57600080fd5b506103bf6108cd3660046153ac565b61289e565b3480156108de57600080fd5b506103ef6108ed3660046153d8565b612924565b3480156108fe57600080fd5b506103ef61090d36600461562c565b61294f565b34801561091e57600080fd5b506103bf61092d3660046153ac565b612c85565b34801561093e57600080fd5b506103ef612c93565b34801561095357600080fd5b506102fb54610548906001600160a01b031681565b34801561097457600080fd5b506103ef6109833660046154bb565b612d68565b34801561099457600080fd5b506109a86109a33660046153ac565b612ea9565b60408051928352602083019190915201610396565b3480156109c957600080fd5b5061064b6109d83660046154bb565b612fc6565b3480156109e957600080fd5b506109f2612fd7565b60405161ffff9091168152602001610396565b348015610a1157600080fd5b5061028e546001600160a01b0316610548565b348015610a3057600080fd5b506102fa54610548906001600160a01b031681565b348015610a5157600080fd5b506102fb54610a6a90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610396565b348015610a8b57600080fd5b50610446610a9a3660046153d8565b61304f565b348015610aab57600080fd5b506103ef61305c565b348015610ac057600080fd5b50610446613112565b348015610ad557600080fd5b50610446610ae436600461562c565b613199565b348015610af557600080fd5b506103ef610b04366004615677565b6131c4565b348015610b1557600080fd5b50610548610b243660046154bb565b61321b565b348015610b3557600080fd5b506102fb54610a6a90600160c01b900463ffffffff1681565b348015610b5a57600080fd5b50610446613246565b348015610b6f57600080fd5b50610160546001600160a01b0316610548565b348015610b8e57600080fd5b506103ef610b9d3660046153d8565b613251565b348015610bae57600080fd5b5061012d546001600160a01b0316610548565b348015610bcd57600080fd5b506103ef610bdc366004615677565b613286565b6060609a8054610bf090615694565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1c90615694565b8015610c695780601f10610c3e57610100808354040283529160200191610c69565b820191906000526020600020905b815481529060010190602001808311610c4c57829003601f168201915b5050505050905090565b600033610c818185856132f3565b60019150505b92915050565b610c95613417565b6001600160a01b038116610cd65760405162461bcd60e51b81526020600482015260036024820152624c363360e81b60448201526064015b60405180910390fd5b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055565b610d01613417565b6001600160a01b038116610d3d5760405162461bcd60e51b8152602060048201526003602482015262130d8d60ea1b6044820152606401610ccd565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1615808015610d805750600054600160ff909116105b80610d9a5750303b158015610d9a575060005460ff166001145b610dfd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ccd565b6000805460ff191660011790558015610e20576000805461ff0019166101001790555b6000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610e60573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e8891908101906156c8565b9050610ed587878784604051602001610ea1919061573f565b60405160208183030381529060405285604051602001610ec1919061576f565b604051602081830303815290604052613478565b610ede836134bc565b610ee7306134ec565b6102f980546001600160a01b0319166001600160a01b0386161790556102fb805467ffffffffffffffff60a01b19166509c40000004b60a21b179055610f2b6121e5565b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055610f546121e5565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055506602aa1efb94e000610303558015610fc8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b60006102fc546102fd54610fe2613246565b610fec91906157ae565b610ff691906157ae565b905090565b60405162461bcd60e51b81526020600482015260036024820152624c343560e81b6044820152600090606401610ccd565b60003361103a858285613596565b611045858585613610565b60019150505b9392505050565b6102fa546001600160a01b0316336001600160a01b03161461109c5760405162461bcd60e51b81526020600482015260036024820152624c333960e81b6044820152606401610ccd565b6110a46137ba565b610300546102ff5460009182915b808210156113795761afc85a106113795760006102ff83815481106110d9576110d96157c1565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925291501561136657805161112890613802565b156111aa576102ff8381548110611141576111416157c1565b60009182526020808320909101829055610301805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177fe78f8e39db67a8c6e0d54c288efc6f296f5d558bc028138a8476c9b97f6fcaa490910155611366565b60026111b4613112565b6111be91906157d7565b81602001516001600160601b0316111561128a5760208101516102ff5460405160019233928792600080516020615e9483398151915292611205929091829160039161581b565b60405180910390a46102ff8381548110611221576112216157c1565b600091825260208083209091018290556102ff805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec90910155611366565b6000806112a8836000015184602001516001600160601b0316612ea9565b91509150856102fe546112bb919061584f565b8211156112ca57505050611379565b6112d481886157ae565b96506112e082876157ae565b9550600183600001516001600160a01b031686600080516020615e94833981519152866020015186600260001960405161131d9493929190615862565b60405180910390a46102ff8581548110611339576113396157c1565b600091825260208220015582516113639083611353611c3f565b6001600160a01b03169190613875565b50505b8261137081615886565b935050506110b2565b836102fc600082825461138c91906157ae565b92505081905550826102fe60008282546113a6919061584f565b909155506113b6905084846157ae565b6102fd60008282546113c8919061584f565b909155505050610300555050565b60405162461bcd60e51b8152602060048201526003602482015262261a1b60e91b6044820152600090606401610ccd565b6000610ff66138d8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036114595760405162461bcd60e51b8152600401610ccd9061589f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661148b61394e565b6001600160a01b0316146114b15760405162461bcd60e51b8152600401610ccd906158eb565b6114ba8161396a565b604080516000808252602082019092526114d691839190613972565b50565b600033610c818185856114ec8383613199565b6114f691906157ae565b6132f3565b610292602052816000526040600020818154811061151857600080fd5b6000918252602090912001546001600160a01b03169150829050565b61153c6137ba565b3361154681613802565b156115635760405162461bcd60e51b8152600401610ccd90615937565b61156c33611c4f565b8211156115a15760405162461bcd60e51b815260206004820152600360248201526209868760eb1b6044820152606401610ccd565b60006102fe54836102fd546115b691906157ae565b6102f95491101591506000906002906001600160a01b031663c8f74bb8336040518263ffffffff1660e01b81526004016115f091906154a7565b602060405180830381865afa15801561160d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116319190615953565b1015801561164257506102fe548411155b9050818061164d5750805b61167f5760405162461bcd60e51b81526020600482015260036024820152624c343960e81b6044820152606401610ccd565b60008061168c3387612ea9565b91509150806102fc60008282546116a391906157ae565b92505081905550816102fe60008282546116bd919061584f565b9091555060019050336001600160a01b0316600019600080516020615e94833981519152898660026000196040516116f8949392919061596c565b60405180910390a461170a3382613add565b6117143383613c12565b50505050505050565b6117256137ba565b3361172f81613802565b1561174c5760405162461bcd60e51b8152600401610ccd90615937565b60006102ff8381548110611762576117626157c1565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150336001600160a01b0316146117de5760405162461bcd60e51b81526020600482015260036024820152624c353760e81b6044820152606401610ccd565b80602001516001600160601b03166102fd60008282546117fe919061584f565b90915550506102ff805484908110611818576118186157c1565b6000918252602082200155600181600001516001600160a01b031684600080516020615e94833981519152846020015185602001516001600019604051611862949392919061581b565b60405180910390a4611885816000015182602001516001600160601b0316613c3f565b505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036118d25760405162461bcd60e51b8152600401610ccd9061589f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661190461394e565b6001600160a01b03161461192a5760405162461bcd60e51b8152600401610ccd906158eb565b6119338261396a565b61193f82826001613972565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146119de5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610ccd565b50600080516020615e2d83398151915290565b6103018181548110611a0257600080fd5b6000918252602090912001546001600160a01b0381169150600160a01b90046001600160601b031682565b6000610ff6613d02565b611a3f613417565b610302546000199060005b81811015611aa457836001600160a01b03166103028281548110611a7057611a706157c1565b6000918252602090912001546001600160a01b031603611a9257809250611aa4565b80611a9c81615886565b915050611a4a565b506000198213611adc5760405162461bcd60e51b8152602060048201526003602482015262261a1960e91b6044820152606401610ccd565b610302611aea60018361584f565b81548110611afa57611afa6157c1565b60009182526020909120015461030280546001600160a01b039092169184908110611b2757611b276157c1565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550610302805480611b6757611b67615987565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b611b96613417565b60405163433e3bad60e11b8152610290600482015261ffff82166024820152733F0Ff9947550d7Cf26549136552C785446ad4Ac59063867c775a9060440160006040518083038186803b158015611bec57600080fd5b505af4158015611c00573d6000803e3d6000fd5b505060405161ffff841681527f3d6d63f501ae621a01c729938fb4428a25138835257943d6b56c49b402ba36329250602001905060405180910390a150565b6102c6546001600160a01b031690565b6000611c5a8261304f565b611c638361249a565b610c8791906157ae565b611c75613417565b60405162461bcd60e51b81526020600482015260036024820152624c363560e81b6044820152606401610ccd565b6102fb546001600160a01b0316336001600160a01b031614611cd75760405162461bcd60e51b8152600401610ccd9061599d565b611cdf6137ba565b60006102ff8281548110611cf557611cf56157c1565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150611d665760405162461bcd60e51b8152602060048201526003602482015262261b1b60e91b6044820152606401610ccd565b8051611d7190613802565b15611da45760405162461bcd60e51b815260206004820152600360248201526204c35360ec1b6044820152606401610ccd565b6002611dae613112565b611db891906157d7565b81602001516001600160601b031611611df95760405162461bcd60e51b81526020600482015260036024820152624c353160e81b6044820152606401610ccd565b600080611e17836000015184602001516001600160601b0316612ea9565b915091506000611e25611c3f565b6102fb546040516370a0823160e01b81526001600160a01b03928316926370a0823192611e57929116906004016154a7565b602060405180830381865afa158015611e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e989190615953565b9050806102fe54611ea991906157ae565b831115611ede5760405162461bcd60e51b8152602060048201526003602482015262261a9960e91b6044820152606401610ccd565b816102fc6000828254611ef191906157ae565b9250508190555083602001516001600160601b03166102fd6000828254611f18919061584f565b9091555050610300548503611f3e576103008054906000611f3883615886565b91905055505b600184600001516001600160a01b031686600080516020615e948339815191528760200151876002600019604051611f799493929190615862565b60405180910390a46102ff8581548110611f9557611f956157c1565b6000918252602082200155808311611fcc57611fc733855185611fb6611c3f565b6001600160a01b0316929190613d71565b612013565b6000611fd8828561584f565b9050806102fe6000828254611fed919061584f565b90915550612002905033865184611fb6611c3f565b84516120119082611353611c3f565b505b61201b613d92565b5050505050565b6102fb546001600160a01b0316336001600160a01b0316146120565760405162461bcd60e51b8152600401610ccd9061599d565b61205e6137ba565b612066611c3f565b6102fb546040516370a0823160e01b81526001600160a01b03928316926370a0823192612098929116906004016154a7565b602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190615953565b81111561210e5760405162461bcd60e51b81526020600482015260036024820152620986a760eb1b6044820152606401610ccd565b6000816102fe5461211f91906157ae565b9050612129613112565b81111561215e5760405162461bcd60e51b81526020600482015260036024820152624c353960e81b6044820152606401610ccd565b816102fe600082825461217191906157ae565b9091555061193f9050333084611fb6611c3f565b61218d613417565b612195611c3f565b6001600160a01b0316826001600160a01b0316036121db5760405162461bcd60e51b81526020600482015260036024820152624c343360e81b6044820152606401610ccd565b61193f8282613df0565b61012d5460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015612230573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff691906159ba565b61225c6137ba565b8161226681613802565b156122835760405162461bcd60e51b8152600401610ccd90615937565b8161228d81613802565b156122aa5760405162461bcd60e51b8152600401610ccd90615937565b6001600160a01b038481166000908152610291602052604090205416156122f95760405162461bcd60e51b8152602060048201526003602482015262261b1960e91b6044820152606401610ccd565b6001600160a01b0384166123355760405162461bcd60e51b815260206004820152600360248201526226189960e91b6044820152606401610ccd565b6001600160a01b0383166123715760405162461bcd60e51b81526020600482015260036024820152624c313360e81b6044820152606401610ccd565b826001600160a01b0316846001600160a01b0316036123b85760405162461bcd60e51b8152602060048201526003602482015262130c4d60ea1b6044820152606401610ccd565b6123c06121e5565b6001600160a01b0316336001600160a01b031614806123e75750336001600160a01b038516145b6124195760405162461bcd60e51b81526020600482015260036024820152624c313560e81b6044820152606401610ccd565b612424846001613ee7565b61242f836001613ee7565b50506001600160a01b039182166000818152610291602090815260408083208054969095166001600160a01b03199687168117909555938252610292815292812080546001810182559082529290209091018054909216179055565b6060609b8054610bf090615694565b6001600160a01b038116600090815260976020526040812054610c87565b6124c0613417565b61030280546001810182556000919091527f552430c2010355dda19e8bae437f75cfb136cb8d667c4c0867367db21eee69b60180546001600160a01b0319166001600160a01b0392909216919091179055565b61251b6137ba565b3361252581613802565b156125425760405162461bcd60e51b8152600401610ccd90615937565b61254b33611c4f565b8211156125805760405162461bcd60e51b81526020600482015260036024820152624c353360e81b6044820152606401610ccd565b6001600160601b038211156125bd5760405162461bcd60e51b8152602060048201526003602482015262130d4d60ea1b6044820152606401610ccd565b6103035434146125f55760405162461bcd60e51b81526020600482015260036024820152624c353560e81b6044820152606401610ccd565b600060405180604001604052806126093390565b6001600160a01b0390811682526001600160601b0386166020909201919091526102f9549192506000916002911663c8f74bb8336040518263ffffffff1660e01b815260040161265991906154a7565b602060405180830381865afa158015612676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269a9190615953565b101580156126ab5750600061030054115b156127195761030080549060006126c1836159d7565b9190505550610300549050816102ff82815481106126e1576126e16157c1565b6000918252602091829020835193909201516001600160601b0316600160a01b026001600160a01b0390931692909217910155612783565b6102ff8054600181810183556000839052845160208601516001600160601b0316600160a01b026001600160a01b03909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec909201919091559054612780919061584f565b90505b836102fd600082825461279691906157ae565b9091555060019050336001600160a01b031682600080516020615e94833981519152878860006000196040516127cf949392919061596c565b60405180910390a46127e13385613add565b6102fa546040516000916001600160a01b03169034908381818185875af1925050503d806000811461282f576040519150601f19603f3d011682016040523d82523d6000602084013e612834565b606091505b505090508061201b5760405162461bcd60e51b8152602060048201526003602482015262261a9b60e91b6044820152606401610ccd565b612873613417565b61030354614e2010156128985760405162461bcd60e51b8152600401610ccd906159ee565b61030355565b600033816128ac8286613199565b90508381101561290c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610ccd565b61291982868684036132f3565b506001949350505050565b61292c613417565b6102f980546001600160a01b0319166001600160a01b0392909216919091179055565b6129576137ba565b8161296181613802565b1561297e5760405162461bcd60e51b8152600401610ccd90615937565b8161298881613802565b156129a55760405162461bcd60e51b8152600401610ccd90615937565b6001600160a01b0384166129e15760405162461bcd60e51b815260206004820152600360248201526226189b60e91b6044820152606401610ccd565b6001600160a01b038316612a1d5760405162461bcd60e51b81526020600482015260036024820152624c313760e81b6044820152606401610ccd565b612a256121e5565b6001600160a01b0316336001600160a01b03161480612a4c5750336001600160a01b038516145b612a7e5760405162461bcd60e51b815260206004820152600360248201526209862760eb1b6044820152606401610ccd565b6001600160a01b0384811660009081526102916020526040902054811690841614612ad15760405162461bcd60e51b81526020600482015260036024820152624c313960e81b6044820152606401610ccd565b612adc846001613ee7565b612ae7836001613ee7565b60001960005b6001600160a01b03851660009081526102926020526040902054811015612b72576001600160a01b0385811660009081526102926020526040902080549188169183908110612b3e57612b3e6157c1565b6000918252602090912001546001600160a01b031603612b6057809150612b72565b80612b6a81615886565b915050612aed565b506000811215612b8457612b84615a0b565b6001600160a01b0380861660009081526102916020908152604080832080546001600160a01b031916905592871682526102929052208054612bc89060019061584f565b81548110612bd857612bd86157c1565b60009182526020808320909101546001600160a01b0387811684526102929092526040909220805491909216919083908110612c1657612c166157c1565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918616815261029290915260409020805480612c5c57612c5c615987565b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b600033610c81818585613610565b612c9b613417565b60006102fe54612ca9611c3f565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612cd491906154a7565b602060405180830381865afa158015612cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d159190615953565b612d1f919061584f565b905060008111612d575760405162461bcd60e51b8152602060048201526003602482015262130d0d60ea1b6044820152606401610ccd565b6114d6612d62611c3f565b82613df0565b612d706137ba565b33612d7a81613802565b15612d975760405162461bcd60e51b8152600401610ccd90615937565b81612da0611c3f565b6001600160a01b03166370a08231336040518263ffffffff1660e01b8152600401612dcb91906154a7565b602060405180830381865afa158015612de8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0c9190615953565b1015612e405760405162461bcd60e51b81526020600482015260036024820152624c343760e81b6044820152606401610ccd565b816102fe6000828254612e5391906157ae565b9091555060009050336001600160a01b0316600019600080516020615e9483398151915285866002600019604051612e8e949392919061596c565b60405180910390a4612ea03383613fbc565b5061193f613d92565b6102f95460405163191ee97760e31b815260009182916002916001600160a01b03169063c8f74bb890612ee09088906004016154a7565b602060405180830381865afa158015612efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f219190615953565b10612f3157508190506000612fbf565b6000612f4e612f4961028e546001600160a01b031690565b61403d565b90506000612f5c85836140aa565b6102fb54909150600090612f7d90600160a01b900463ffffffff16846140e8565b90506000612f8c606485614114565b612f968385615a21565b612fa091906157d7565b9050612fac8185614142565b9450612fb8858861584f565b9550505050505b9250929050565b6102ff8181548110611a0257600080fd5b60405163106d64cf60e31b81526102906004820152600090733F0Ff9947550d7Cf26549136552C785446ad4Ac59063836b267890602401602060405180830381865af415801561302b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190615a38565b6000610c87826001614179565b613064613417565b60006102fc541161309d5760405162461bcd60e51b815260206004820152600360248201526204c36360ec1b6044820152606401610ccd565b6102fc546102fe5410156130d95760405162461bcd60e51b81526020600482015260036024820152624c363160e81b6044820152606401610ccd565b6102fc546102fe60008282546130ef919061584f565b90915550506102fc805460009091556114d66131096121e5565b82611353611c3f565b60008061312b612f4961028e546001600160a01b031690565b9050600061314061313a610fd0565b836140aa565b6102fb5490915060009061316190600160c01b900463ffffffff16846140e8565b90506000613170606485614114565b61317a8385615a21565b61318491906157d7565b90506131908185614142565b94505050505090565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6131cc613417565b614e2063ffffffff821611156131f45760405162461bcd60e51b8152600401610ccd906159ee565b6102fb805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b610302818154811061322c57600080fd5b6000918252602090912001546001600160a01b0316905081565b6000610ff660995490565b613259613417565b60405162461bcd60e51b8152602060048201526002602482015261098760f31b6044820152606401610ccd565b61328e613417565b61271063ffffffff821611156132cc5760405162461bcd60e51b81526020600482015260036024820152624c343160e81b6044820152606401610ccd565b6102fb805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b6001600160a01b0383166133555760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610ccd565b6001600160a01b0382166133b65760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610ccd565b6001600160a01b0383811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b336134206121e5565b6001600160a01b0316146134765760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ccd565b565b600054610100900460ff1661349f5760405162461bcd60e51b8152600401610ccd90615a55565b6134aa8585856146df565b6134b48282614739565b61201b61476a565b600054610100900460ff166134e35760405162461bcd60e51b8152600401610ccd90615a55565b6114d681614791565b600054610100900460ff166135135760405162461bcd60e51b8152600401610ccd90615a55565b61028e80546001600160a01b0319166001600160a01b03831617905560405163433e3bad60e11b8152610290600482015260006024820152733F0Ff9947550d7Cf26549136552C785446ad4Ac59063867c775a9060440160006040518083038186803b15801561358257600080fd5b505af415801561201b573d6000803e3d6000fd5b60006135a28484613199565b9050600019811461360a57818110156135fd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610ccd565b61360a84848484036132f3565b50505050565b6001600160a01b0383166136745760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610ccd565b6001600160a01b0382166136d65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610ccd565b6136e1838383614833565b6001600160a01b038316600090815260976020526040902054818110156137595760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610ccd565b6001600160a01b038085166000818152609760205260408082208686039055928616808252908390208054860190559151600080516020615e74833981519152906137a79086815260200190565b60405180910390a361360a848484614872565b6137c2611a2d565b156134765760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ccd565b6101935460405163fe575a8760e01b81526000916001600160a01b03169063fe575a87906138349085906004016154a7565b602060405180830381865afa158015613851573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c879190615aa0565b6040516001600160a01b03831660248201526044810182905261188590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614973565b6102c6546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048083019260209291908290030181865afa92505050801561393f575060408051601f3d908101601f1916820190925261393c91810190615ac2565b60015b6139495750601290565b919050565b600080516020615e2d833981519152546001600160a01b031690565b6114d6613417565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156139a55761188583614a48565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156139ff575060408051601f3d908101601f191682019092526139fc91810190615953565b60015b613a625760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610ccd565b600080516020615e2d8339815191528114613ad15760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610ccd565b50611885838383614ae4565b6001600160a01b038216613b3d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610ccd565b613b4982600083614833565b6001600160a01b03821660009081526097602052604090205481811015613bbd5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610ccd565b6001600160a01b0383166000818152609760209081526040808320868603905560998054879003905551858152919291600080516020615e74833981519152910160405180910390a361188583600084614872565b6000613c1e3383613add565b6102c654613c36906001600160a01b03168484613875565b50600192915050565b6001600160a01b038216613c955760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610ccd565b613ca160008383614833565b8060996000828254613cb391906157ae565b90915550506001600160a01b038216600081815260976020908152604080832080548601905551848152600080516020615e74833981519152910160405180910390a361193f60008383614872565b6101605460408051635c975abb60e01b815290516000926001600160a01b031691635c975abb9160048083019260209291908290030181865afa158015613d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190615aa0565b61360a846323b872dd60e01b8585856040516024016138a193929190615ae5565b6000613d9c613112565b9050806102fe5411613dab5750565b6000816102fe54613dbc919061584f565b9050806102fe6000828254613dd1919061584f565b90915550506102fb5461193f906001600160a01b031682611353611c3f565b613df8613417565b60008111613e2e5760405162461bcd60e51b815260206004820152600360248201526204c31360ec1b6044820152606401610ccd565b6040516370a0823160e01b8152829082906001600160a01b038316906370a0823190613e5e9030906004016154a7565b602060405180830381865afa158015613e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9f9190615953565b1015613ed35760405162461bcd60e51b81526020600482015260036024820152624c313160e81b6044820152606401610ccd565b6118856001600160a01b0382163384613875565b6102935460ff1615613ef7575050565b6001600160a01b038216600090815261028f602052604090205464ffffffffff428116911603613f25575050565b6001600160a01b0380831660009081526102916020526040902054168015613f51576118858183613ee7565b6000613f5d8484614179565b90508015613fb357610293805460ff191660011790556000613f7f8583614b09565b610293805460ff19169055905080613fb1576001600160a01b038516600090815261028f602052604090206003018290555b505b61360a84614b60565b60003330810361401a5760405162461bcd60e51b815260206004820152602360248201527f4552433230577261707065723a20777261707065722063616e2774206465706f6044820152621cda5d60ea1b6064820152608401610ccd565b6102c654614033906001600160a01b0316823086613d71565b610c818484613c3f565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561407d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140a19190615ac2565b60ff1692915050565b600060038210156140dc576140c082600661584f565b6140cb90600a615bed565b6140d59084615a21565b9050610c87565b61104b836103e8615a21565b600060038210156140ff576140d5836103e8615a21565b61410a82600a615bed565b61104b9084615a21565b6000600382101561412c576140d583620f4240615a21565b6141378260036157ae565b61410a90600a615bed565b6000600382101561416d5761415882600661584f565b61416390600a615bed565b6140d590846157d7565b61104b6103e8846157d7565b6001600160a01b038216600090815261028f602090815260408083208151608081018352815464ffffffffff16818401908152835180850190945260018301548452600283015463ffffffff168486015260608201939093529182526003015491810191909152816141ea85614cc2565b82515190915064ffffffffff161580614201575080155b1561421157600092505050610c87565b815160200151604051630b27cfb160e31b8152600090733F0Ff9947550d7Cf26549136552C785446ad4Ac59063593e7d889061425590610290908690600401615bf9565b6040805180830381865af4158015614271573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142959190615c1d565b60405163038255fd60e11b81526102906004820152909150600090733F0Ff9947550d7Cf26549136552C785446ad4Ac590630704abfa906024016040805180830381865af41580156142eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061430f9190615c68565b905084602001519550733F0Ff9947550d7Cf26549136552C785446ad4Ac5634ead0c5384836040518363ffffffff1660e01b8152600401614351929190615c94565b602060405180830381865af415801561436e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143929190615aa0565b6146a357604051633e1e5c5360e11b8152600090733F0Ff9947550d7Cf26549136552C785446ad4Ac590637c3cb8a6906143d0908790600401615cc8565b6040805180830381865af41580156143ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144109190615c68565b604051630b27cfb160e31b8152909150600090733F0Ff9947550d7Cf26549136552C785446ad4Ac59063593e7d889061445190610290908690600401615bf9565b6040805180830381865af415801561446d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144919190615c1d565b875151602082015186519293506144bf928c6144ae5760006144b0565b8b5b6144ba908b6157ae565b614d6b565b6144c990896157ae565b97505b819450809350733F0Ff9947550d7Cf26549136552C785446ad4Ac5634ead0c5386856040518363ffffffff1660e01b815260040161450b929190615c94565b602060405180830381865af4158015614528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061454c9190615aa0565b61467657604051633e1e5c5360e11b8152733F0Ff9947550d7Cf26549136552C785446ad4Ac590637c3cb8a690614587908890600401615cc8565b6040805180830381865af41580156145a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145c79190615c68565b604051630b27cfb160e31b8152909250733F0Ff9947550d7Cf26549136552C785446ad4Ac59063593e7d889061460590610290908690600401615bf9565b6040805180830381865af4158015614621573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146459190615c1d565b90506146658460200151826020015186600001518c6144ae5760006144b0565b61466f90896157ae565b97506144cc565b61469084602001514286600001518c6144ae5760006144b0565b61469a90896157ae565b975050506146d4565b84515182516146c7919042908a6146bb5760006146bd565b895b6144ba90896157ae565b6146d190876157ae565b95505b505050505092915050565b600054610100900460ff166147065760405162461bcd60e51b8152600401610ccd90615a55565b61470e61476a565b61471783614e57565b61471f614e87565b61472882614eb6565b61473181614f00565b61188561476a565b600054610100900460ff166147605760405162461bcd60e51b8152600401610ccd90615a55565b61193f8282614f4a565b600054610100900460ff166134765760405162461bcd60e51b8152600401610ccd90615a55565b600054610100900460ff166147b85760405162461bcd60e51b8152600401610ccd90615a55565b306001600160a01b038216036148105760405162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a2063616e6e6f742073656c66207772617000006044820152606401610ccd565b6102c680546001600160a01b0319166001600160a01b0392909216919091179055565b61483e838383614f8a565b6001600160a01b0383161561485857614858836001613ee7565b6001600160a01b0382161561188557611885826001613ee7565b6001600160a01b038316158061488f57506001600160a01b038216155b156148cf577f980f7e6fb44009001d533a10bc3bd558b4efe22dcb4888bca4767aa93c71ce1f6148bd610fd0565b60405190815260200160405180910390a15b60005b6103025481101561360a5761030281815481106148f1576148f16157c1565b600091825260209091200154604051636e0d037d60e11b81526001600160a01b039091169063dc1a06fa9061492e90879087908790600401615ae5565b600060405180830381600087803b15801561494857600080fd5b505af115801561495c573d6000803e3d6000fd5b50505050808061496b90615886565b9150506148d2565b60006149c8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614feb9092919063ffffffff16565b90508051600014806149e95750808060200190518101906149e99190615aa0565b6118855760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610ccd565b6001600160a01b0381163b614ab55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610ccd565b600080516020615e2d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b614aed83614ffa565b600082511180614afa5750805b156118855761360a838361503a565b6000826001600160a01b03167f05a71d417f891ba4b7a94b48d1b1f4b59b070921cba593b3c72a05a5587a78a9614b3f8561249a565b60408051918252602082018690520160405180910390a2613c368383613c3f565b6001600160a01b038116600090815261028f602052604090819020805464ffffffffff19164264ffffffffff161790555163038255fd60e11b81526102906004820152733F0Ff9947550d7Cf26549136552C785446ad4Ac590630704abfa906024016040805180830381865af4158015614bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c029190615c68565b6001600160a01b038216600090815261028f602090815260408220835160018201559201516002909201805463ffffffff191663ffffffff909316929092179091555b6001600160a01b0382166000908152610292602052604090205481101561193f576001600160a01b0382166000908152610292602052604090208054614cb0919083908110614c9657614c966157c1565b6000918252602090912001546001600160a01b0316614b60565b80614cba81615886565b915050614c45565b6000614ccd8261505f565b614cd790826157ae565b905060005b6001600160a01b03831660009081526102926020526040902054811015614d65576001600160a01b0383166000908152610292602052604090208054614d47919083908110614d2d57614d2d6157c1565b6000918252602090912001546001600160a01b0316614cc2565b614d5190836157ae565b915080614d5d81615886565b915050614cdc565b50919050565b600080614d84612f4961028e546001600160a01b031690565b90506000614da2614d958888615ce5565b64ffffffffff1683614114565b90506000614db46301e1338084614114565b614dbf600185614114565b614dc99084615a21565b614dd391906157d7565b90506000614de58761ffff16856140e8565b90506000614df4600186614114565b614dfe8385615a21565b614e0891906157d7565b90506000614e1688876140aa565b90506000614e25606488614114565b614e2f8484615a21565b614e3991906157d7565b9050614e458188614142565b9750505050505050505b949350505050565b600054610100900460ff16614e7e5760405162461bcd60e51b8152600401610ccd90615a55565b6114d68161506a565b600054610100900460ff16614eae5760405162461bcd60e51b8152600401610ccd90615a55565b6134766150b4565b600054610100900460ff16614edd5760405162461bcd60e51b8152600401610ccd90615a55565b61016080546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16614f275760405162461bcd60e51b8152600401610ccd90615a55565b61019380546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16614f715760405162461bcd60e51b8152600401610ccd90615a55565b609a614f7d8382615d50565b50609b6118858282615d50565b614f926137ba565b82614f9c81613802565b15614fb95760405162461bcd60e51b8152600401610ccd90615937565b82614fc381613802565b15614fe05760405162461bcd60e51b8152600401610ccd90615937565b61201b8585856150e7565b6060614e4f848460008561514f565b61500381614a48565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061104b8383604051806060016040528060278152602001615e4d6027913961522a565b6000610c878261249a565b600054610100900460ff166150915760405162461bcd60e51b8152600401610ccd90615a55565b61012d80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166150db5760405162461bcd60e51b8152600401610ccd90615a55565b60c9805460ff19169055565b6150ef611a2d565b156118855760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610ccd565b6060824710156151b05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610ccd565b600080866001600160a01b031685876040516151cc9190615e10565b60006040518083038185875af1925050503d8060008114615209576040519150601f19603f3d011682016040523d82523d6000602084013e61520e565b606091505b509150915061521f878383876152a2565b979650505050505050565b6060600080856001600160a01b0316856040516152479190615e10565b600060405180830381855af49150503d8060008114615282576040519150601f19603f3d011682016040523d82523d6000602084013e615287565b606091505b5091509150615298868383876152a2565b9695505050505050565b6060831561531157825160000361530a576001600160a01b0385163b61530a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ccd565b5081614e4f565b614e4f83838151156153265781518083602001fd5b8060405162461bcd60e51b8152600401610ccd9190615364565b60005b8381101561535b578181015183820152602001615343565b50506000910152565b6020815260008251806020840152615383816040850160208701615340565b601f01601f19169190910160400192915050565b6001600160a01b03811681146114d657600080fd5b600080604083850312156153bf57600080fd5b82356153ca81615397565b946020939093013593505050565b6000602082840312156153ea57600080fd5b813561104b81615397565b600080600080600060a0868803121561540d57600080fd5b853561541881615397565b9450602086013561542881615397565b9350604086013561543881615397565b9250606086013561544881615397565b9150608086013561545881615397565b809150509295509295909350565b60008060006060848603121561547b57600080fd5b833561548681615397565b9250602084013561549681615397565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b6000602082840312156154cd57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561550d5761550d6154d4565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561553c5761553c6154d4565b604052919050565b600067ffffffffffffffff82111561555e5761555e6154d4565b50601f01601f191660200190565b6000806040838503121561557f57600080fd5b823561558a81615397565b9150602083013567ffffffffffffffff8111156155a657600080fd5b8301601f810185136155b757600080fd5b80356155ca6155c582615544565b615513565b8181528660208385010111156155df57600080fd5b816020840160208301376000602083830101528093505050509250929050565b61ffff811681146114d657600080fd5b60006020828403121561562157600080fd5b813561104b816155ff565b6000806040838503121561563f57600080fd5b823561564a81615397565b9150602083013561565a81615397565b809150509250929050565b63ffffffff811681146114d657600080fd5b60006020828403121561568957600080fd5b813561104b81615665565b600181811c908216806156a857607f821691505b602082108103614d6557634e487b7160e01b600052602260045260246000fd5b6000602082840312156156da57600080fd5b815167ffffffffffffffff8111156156f157600080fd5b8201601f8101841361570257600080fd5b80516157106155c582615544565b81815285602083850101111561572557600080fd5b615736826020830160208601615340565b95945050505050565b6702632b233b4ba3c960c51b815260008251615762816008850160208701615340565b9190910160080192915050565b601360fa1b81526000825161578b816001850160208701615340565b9190910160010192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c8757610c87615798565b634e487b7160e01b600052603260045260246000fd5b6000826157f457634e487b7160e01b600052601260045260246000fd5b500490565b6004811061581757634e487b7160e01b600052602160045260246000fd5b9052565b6001600160601b038581168252841660208201526080810161584060408301856157f9565b82606083015295945050505050565b81810381811115610c8757610c87615798565b6001600160601b0385168152602081018490526080810161584060408301856157f9565b60006001820161589857615898615798565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252600290820152614c3960f01b604082015260600190565b60006020828403121561596557600080fd5b5051919050565b848152602081018490526080810161584060408301856157f9565b634e487b7160e01b600052603160045260246000fd5b60208082526003908201526204c34360ec1b604082015260600190565b6000602082840312156159cc57600080fd5b815161104b81615397565b6000816159e6576159e6615798565b506000190190565b60208082526003908201526209870760eb1b604082015260600190565b634e487b7160e01b600052600160045260246000fd5b8082028115828204841417610c8757610c87615798565b600060208284031215615a4a57600080fd5b815161104b816155ff565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615ab257600080fd5b8151801515811461104b57600080fd5b600060208284031215615ad457600080fd5b815160ff8116811461104b57600080fd5b6001600160a01b039384168152919092166020820152604081019190915260600190565b600181815b80851115615b44578160001904821115615b2a57615b2a615798565b80851615615b3757918102915b93841c9390800290615b0e565b509250929050565b600082615b5b57506001610c87565b81615b6857506000610c87565b8160018114615b7e5760028114615b8857615ba4565b6001915050610c87565b60ff841115615b9957615b99615798565b50506001821b610c87565b5060208310610133831016604e8410600b8410161715615bc7575081810a610c87565b615bd18383615b09565b8060001904821115615be557615be5615798565b029392505050565b600061104b8383615b4c565b8281526060810161104b60208301848051825260209081015163ffffffff16910152565b600060408284031215615c2f57600080fd5b615c376154ea565b8251615c42816155ff565b8152602083015164ffffffffff81168114615c5c57600080fd5b60208201529392505050565b600060408284031215615c7a57600080fd5b615c826154ea565b825181526020830151615c5c81615665565b8251815260208084015163ffffffff16908201526080810182516040830152602083015163ffffffff16606083015261104b565b8151815260208083015163ffffffff169082015260408101610c87565b64ffffffffff828116828216039080821115615d0357615d03615798565b5092915050565b601f82111561188557600081815260208120601f850160051c81016020861015615d315750805b601f850160051c820191505b81811015610fc857828155600101615d3d565b815167ffffffffffffffff811115615d6a57615d6a6154d4565b615d7e81615d788454615694565b84615d0a565b602080601f831160018114615db35760008415615d9b5750858301515b600019600386901b1c1916600185901b178555610fc8565b600085815260208120601f198616915b82811015615de257888601518255948401946001909101908401615dc3565b5085821015615e005787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251615e22818460208701615340565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efd58e94604d90293a1c1ad95bfe6a6e6c352c33c5774a4b6b4f4b6f7460da29c5a2646970667358221220796e679a619b27b0c2166aa2b4934a098e55727f912cd99f85a1da2f76dfe77764736f6c63430008120033", + "deployedBytecode": "0x60806040526004361061036f5760003560e01c80638980f11f116101c8578063c822adda116100f8578063dd62ed3e1161009b578063dd62ed3e14610ac9578063ee1335d114610ae9578063ee153c4f14610b09578063ef2591af14610b29578063ef356a7914610b4e578063f12d54d814610b63578063f2fde38b14610b82578063f762e73414610ba2578063f94ce2c214610bc157600080fd5b8063c822adda146109bd578063c89d5b8b146109dd578063cafb220214610a05578063cdc1842414610a24578063d038875c14610a45578063d039981b14610a7f578063d294f09314610a9f578063db84faac14610ab457600080fd5b80639f79b1c61161016b5780639f79b1c614610892578063a457c2d7146108b2578063a64c91cc146108d2578063a8f76320146108f2578063a9059cbb14610912578063b2de2a4314610932578063b60d428814610947578063b6b55f2514610968578063bacd609e1461098857600080fd5b80638980f11f1461079e5780638d8e6bd7146107be5780638da5cb5b146107f557806392e5ced71461080a57806395d89b411461082a57806399a03c701461083f5780639c2719751461085f5780639ee679e81461087f57600080fd5b80634134bee9116102a35780636d3a4ac8116102465780636d3a4ac8146106a75780636f307dc3146106c757806370a08231146106dc578063715018a6146106fc578063734d8287146107115780637594d0b51461072857806375a5652b1461073f5780637c2edb161461075f5780638370e1f71461077e57600080fd5b80634134bee9146105ac57806345b05d09146105cc5780634f1ef286146105ec57806352d1902d146105ff57806353ac4b661461061457806353d3a42f1461062b5780635c975abb146106725780635f0e8e371461068757600080fd5b806323b872dd1161031657806323b872dd1461048b5780632a1b8b1c146104ab5780632f4f21e2146104c0578063313ce567146104e05780633659cfe614610507578063391d85ec1461052757806339509351146105555780633e7ae353146105755780633fd52fb91461059557600080fd5b806306fdde0314610374578063095ea7b31461039f5780630d174c24146103cf5780630e21750f146103f15780631459457a1461041157806318160ddd146104315780631c19be6d14610454578063205c28781461046b575b600080fd5b34801561038057600080fd5b50610389610be1565b6040516103969190615364565b60405180910390f35b3480156103ab57600080fd5b506103bf6103ba3660046153ac565b610c73565b6040519015158152602001610396565b3480156103db57600080fd5b506103ef6103ea3660046153d8565b610c8d565b005b3480156103fd57600080fd5b506103ef61040c3660046153d8565b610cf9565b34801561041d57600080fd5b506103ef61042c3660046153f5565b610d60565b34801561043d57600080fd5b50610446610fd0565b604051908152602001610396565b34801561046057600080fd5b506104466102fe5481565b34801561047757600080fd5b506103bf6104863660046153ac565b610ffb565b34801561049757600080fd5b506103bf6104a6366004615466565b61102c565b3480156104b757600080fd5b506103ef611052565b3480156104cc57600080fd5b506103bf6104db3660046153ac565b6113d6565b3480156104ec57600080fd5b506104f5611407565b60405160ff9091168152602001610396565b34801561051357600080fd5b506103ef6105223660046153d8565b611411565b34801561053357600080fd5b506102f954610548906001600160a01b031681565b60405161039691906154a7565b34801561056157600080fd5b506103bf6105703660046153ac565b6114d9565b34801561058157600080fd5b506105486105903660046153ac565b6114fb565b3480156105a157600080fd5b506104466103035481565b3480156105b857600080fd5b506103ef6105c73660046154bb565b611534565b3480156105d857600080fd5b506103ef6105e73660046154bb565b61171d565b6103ef6105fa36600461556c565b61188a565b34801561060b57600080fd5b50610446611943565b34801561062057600080fd5b506104466102fd5481565b34801561063757600080fd5b5061064b6106463660046154bb565b6119f1565b604080516001600160a01b0390931683526001600160601b03909116602083015201610396565b34801561067e57600080fd5b506103bf611a2d565b34801561069357600080fd5b506103ef6106a23660046153d8565b611a37565b3480156106b357600080fd5b506103ef6106c236600461560f565b611b8e565b3480156106d357600080fd5b50610548611c3f565b3480156106e857600080fd5b506104466106f73660046153d8565b611c4f565b34801561070857600080fd5b506103ef611c6d565b34801561071d57600080fd5b506104466102fc5481565b34801561073457600080fd5b506104466103005481565b34801561074b57600080fd5b506103ef61075a3660046154bb565b611ca3565b34801561076b57600080fd5b50610193546001600160a01b0316610548565b34801561078a57600080fd5b506103ef6107993660046154bb565b612022565b3480156107aa57600080fd5b506103ef6107b93660046153ac565b612185565b3480156107ca57600080fd5b506105486107d93660046153d8565b610291602052600090815260409020546001600160a01b031681565b34801561080157600080fd5b506105486121e5565b34801561081657600080fd5b506103ef61082536600461562c565b612254565b34801561083657600080fd5b5061038961248b565b34801561084b57600080fd5b5061044661085a3660046153d8565b61249a565b34801561086b57600080fd5b506103ef61087a3660046153d8565b6124b8565b6103ef61088d3660046154bb565b612513565b34801561089e57600080fd5b506103ef6108ad3660046154bb565b61286b565b3480156108be57600080fd5b506103bf6108cd3660046153ac565b61289e565b3480156108de57600080fd5b506103ef6108ed3660046153d8565b612924565b3480156108fe57600080fd5b506103ef61090d36600461562c565b61294f565b34801561091e57600080fd5b506103bf61092d3660046153ac565b612c85565b34801561093e57600080fd5b506103ef612c93565b34801561095357600080fd5b506102fb54610548906001600160a01b031681565b34801561097457600080fd5b506103ef6109833660046154bb565b612d68565b34801561099457600080fd5b506109a86109a33660046153ac565b612ea9565b60408051928352602083019190915201610396565b3480156109c957600080fd5b5061064b6109d83660046154bb565b612fc6565b3480156109e957600080fd5b506109f2612fd7565b60405161ffff9091168152602001610396565b348015610a1157600080fd5b5061028e546001600160a01b0316610548565b348015610a3057600080fd5b506102fa54610548906001600160a01b031681565b348015610a5157600080fd5b506102fb54610a6a90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610396565b348015610a8b57600080fd5b50610446610a9a3660046153d8565b61304f565b348015610aab57600080fd5b506103ef61305c565b348015610ac057600080fd5b50610446613112565b348015610ad557600080fd5b50610446610ae436600461562c565b613199565b348015610af557600080fd5b506103ef610b04366004615677565b6131c4565b348015610b1557600080fd5b50610548610b243660046154bb565b61321b565b348015610b3557600080fd5b506102fb54610a6a90600160c01b900463ffffffff1681565b348015610b5a57600080fd5b50610446613246565b348015610b6f57600080fd5b50610160546001600160a01b0316610548565b348015610b8e57600080fd5b506103ef610b9d3660046153d8565b613251565b348015610bae57600080fd5b5061012d546001600160a01b0316610548565b348015610bcd57600080fd5b506103ef610bdc366004615677565b613286565b6060609a8054610bf090615694565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1c90615694565b8015610c695780601f10610c3e57610100808354040283529160200191610c69565b820191906000526020600020905b815481529060010190602001808311610c4c57829003601f168201915b5050505050905090565b600033610c818185856132f3565b60019150505b92915050565b610c95613417565b6001600160a01b038116610cd65760405162461bcd60e51b81526020600482015260036024820152624c363360e81b60448201526064015b60405180910390fd5b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055565b610d01613417565b6001600160a01b038116610d3d5760405162461bcd60e51b8152602060048201526003602482015262130d8d60ea1b6044820152606401610ccd565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff1615808015610d805750600054600160ff909116105b80610d9a5750303b158015610d9a575060005460ff166001145b610dfd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ccd565b6000805460ff191660011790558015610e20576000805461ff0019166101001790555b6000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610e60573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e8891908101906156c8565b9050610ed587878784604051602001610ea1919061573f565b60405160208183030381529060405285604051602001610ec1919061576f565b604051602081830303815290604052613478565b610ede836134bc565b610ee7306134ec565b6102f980546001600160a01b0319166001600160a01b0386161790556102fb805467ffffffffffffffff60a01b19166509c40000004b60a21b179055610f2b6121e5565b6102fa80546001600160a01b0319166001600160a01b0392909216919091179055610f546121e5565b6102fb80546001600160a01b0319166001600160a01b0392909216919091179055506602aa1efb94e000610303558015610fc8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b60006102fc546102fd54610fe2613246565b610fec91906157ae565b610ff691906157ae565b905090565b60405162461bcd60e51b81526020600482015260036024820152624c343560e81b6044820152600090606401610ccd565b60003361103a858285613596565b611045858585613610565b60019150505b9392505050565b6102fa546001600160a01b0316336001600160a01b03161461109c5760405162461bcd60e51b81526020600482015260036024820152624c333960e81b6044820152606401610ccd565b6110a46137ba565b610300546102ff5460009182915b808210156113795761afc85a106113795760006102ff83815481106110d9576110d96157c1565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925291501561136657805161112890613802565b156111aa576102ff8381548110611141576111416157c1565b60009182526020808320909101829055610301805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177fe78f8e39db67a8c6e0d54c288efc6f296f5d558bc028138a8476c9b97f6fcaa490910155611366565b60026111b4613112565b6111be91906157d7565b81602001516001600160601b0316111561128a5760208101516102ff5460405160019233928792600080516020615e9483398151915292611205929091829160039161581b565b60405180910390a46102ff8381548110611221576112216157c1565b600091825260208083209091018290556102ff805460018101825592528251908301516001600160601b0316600160a01b026001600160a01b0391909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec90910155611366565b6000806112a8836000015184602001516001600160601b0316612ea9565b91509150856102fe546112bb919061584f565b8211156112ca57505050611379565b6112d481886157ae565b96506112e082876157ae565b9550600183600001516001600160a01b031686600080516020615e94833981519152866020015186600260001960405161131d9493929190615862565b60405180910390a46102ff8581548110611339576113396157c1565b600091825260208220015582516113639083611353611c3f565b6001600160a01b03169190613875565b50505b8261137081615886565b935050506110b2565b836102fc600082825461138c91906157ae565b92505081905550826102fe60008282546113a6919061584f565b909155506113b6905084846157ae565b6102fd60008282546113c8919061584f565b909155505050610300555050565b60405162461bcd60e51b8152602060048201526003602482015262261a1b60e91b6044820152600090606401610ccd565b6000610ff66138d8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036114595760405162461bcd60e51b8152600401610ccd9061589f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661148b61394e565b6001600160a01b0316146114b15760405162461bcd60e51b8152600401610ccd906158eb565b6114ba8161396a565b604080516000808252602082019092526114d691839190613972565b50565b600033610c818185856114ec8383613199565b6114f691906157ae565b6132f3565b610292602052816000526040600020818154811061151857600080fd5b6000918252602090912001546001600160a01b03169150829050565b61153c6137ba565b3361154681613802565b156115635760405162461bcd60e51b8152600401610ccd90615937565b61156c33611c4f565b8211156115a15760405162461bcd60e51b815260206004820152600360248201526209868760eb1b6044820152606401610ccd565b60006102fe54836102fd546115b691906157ae565b6102f95491101591506000906002906001600160a01b031663c8f74bb8336040518263ffffffff1660e01b81526004016115f091906154a7565b602060405180830381865afa15801561160d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116319190615953565b1015801561164257506102fe548411155b9050818061164d5750805b61167f5760405162461bcd60e51b81526020600482015260036024820152624c343960e81b6044820152606401610ccd565b60008061168c3387612ea9565b91509150806102fc60008282546116a391906157ae565b92505081905550816102fe60008282546116bd919061584f565b9091555060019050336001600160a01b0316600019600080516020615e94833981519152898660026000196040516116f8949392919061596c565b60405180910390a461170a3382613add565b6117143383613c12565b50505050505050565b6117256137ba565b3361172f81613802565b1561174c5760405162461bcd60e51b8152600401610ccd90615937565b60006102ff8381548110611762576117626157c1565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150336001600160a01b0316146117de5760405162461bcd60e51b81526020600482015260036024820152624c353760e81b6044820152606401610ccd565b80602001516001600160601b03166102fd60008282546117fe919061584f565b90915550506102ff805484908110611818576118186157c1565b6000918252602082200155600181600001516001600160a01b031684600080516020615e94833981519152846020015185602001516001600019604051611862949392919061581b565b60405180910390a4611885816000015182602001516001600160601b0316613c3f565b505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036118d25760405162461bcd60e51b8152600401610ccd9061589f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661190461394e565b6001600160a01b03161461192a5760405162461bcd60e51b8152600401610ccd906158eb565b6119338261396a565b61193f82826001613972565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146119de5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610ccd565b50600080516020615e2d83398151915290565b6103018181548110611a0257600080fd5b6000918252602090912001546001600160a01b0381169150600160a01b90046001600160601b031682565b6000610ff6613d02565b611a3f613417565b610302546000199060005b81811015611aa457836001600160a01b03166103028281548110611a7057611a706157c1565b6000918252602090912001546001600160a01b031603611a9257809250611aa4565b80611a9c81615886565b915050611a4a565b506000198213611adc5760405162461bcd60e51b8152602060048201526003602482015262261a1960e91b6044820152606401610ccd565b610302611aea60018361584f565b81548110611afa57611afa6157c1565b60009182526020909120015461030280546001600160a01b039092169184908110611b2757611b276157c1565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550610302805480611b6757611b67615987565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b611b96613417565b60405163433e3bad60e11b8152610290600482015261ffff8216602482015273__$3728f51d90da6977d2525dcec632daa0b3$__9063867c775a9060440160006040518083038186803b158015611bec57600080fd5b505af4158015611c00573d6000803e3d6000fd5b505060405161ffff841681527f3d6d63f501ae621a01c729938fb4428a25138835257943d6b56c49b402ba36329250602001905060405180910390a150565b6102c6546001600160a01b031690565b6000611c5a8261304f565b611c638361249a565b610c8791906157ae565b611c75613417565b60405162461bcd60e51b81526020600482015260036024820152624c363560e81b6044820152606401610ccd565b6102fb546001600160a01b0316336001600160a01b031614611cd75760405162461bcd60e51b8152600401610ccd9061599d565b611cdf6137ba565b60006102ff8281548110611cf557611cf56157c1565b6000918252602091829020604080518082019091529101546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092529150611d665760405162461bcd60e51b8152602060048201526003602482015262261b1b60e91b6044820152606401610ccd565b8051611d7190613802565b15611da45760405162461bcd60e51b815260206004820152600360248201526204c35360ec1b6044820152606401610ccd565b6002611dae613112565b611db891906157d7565b81602001516001600160601b031611611df95760405162461bcd60e51b81526020600482015260036024820152624c353160e81b6044820152606401610ccd565b600080611e17836000015184602001516001600160601b0316612ea9565b915091506000611e25611c3f565b6102fb546040516370a0823160e01b81526001600160a01b03928316926370a0823192611e57929116906004016154a7565b602060405180830381865afa158015611e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e989190615953565b9050806102fe54611ea991906157ae565b831115611ede5760405162461bcd60e51b8152602060048201526003602482015262261a9960e91b6044820152606401610ccd565b816102fc6000828254611ef191906157ae565b9250508190555083602001516001600160601b03166102fd6000828254611f18919061584f565b9091555050610300548503611f3e576103008054906000611f3883615886565b91905055505b600184600001516001600160a01b031686600080516020615e948339815191528760200151876002600019604051611f799493929190615862565b60405180910390a46102ff8581548110611f9557611f956157c1565b6000918252602082200155808311611fcc57611fc733855185611fb6611c3f565b6001600160a01b0316929190613d71565b612013565b6000611fd8828561584f565b9050806102fe6000828254611fed919061584f565b90915550612002905033865184611fb6611c3f565b84516120119082611353611c3f565b505b61201b613d92565b5050505050565b6102fb546001600160a01b0316336001600160a01b0316146120565760405162461bcd60e51b8152600401610ccd9061599d565b61205e6137ba565b612066611c3f565b6102fb546040516370a0823160e01b81526001600160a01b03928316926370a0823192612098929116906004016154a7565b602060405180830381865afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190615953565b81111561210e5760405162461bcd60e51b81526020600482015260036024820152620986a760eb1b6044820152606401610ccd565b6000816102fe5461211f91906157ae565b9050612129613112565b81111561215e5760405162461bcd60e51b81526020600482015260036024820152624c353960e81b6044820152606401610ccd565b816102fe600082825461217191906157ae565b9091555061193f9050333084611fb6611c3f565b61218d613417565b612195611c3f565b6001600160a01b0316826001600160a01b0316036121db5760405162461bcd60e51b81526020600482015260036024820152624c343360e81b6044820152606401610ccd565b61193f8282613df0565b61012d5460408051638da5cb5b60e01b815290516000926001600160a01b031691638da5cb5b9160048083019260209291908290030181865afa158015612230573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff691906159ba565b61225c6137ba565b8161226681613802565b156122835760405162461bcd60e51b8152600401610ccd90615937565b8161228d81613802565b156122aa5760405162461bcd60e51b8152600401610ccd90615937565b6001600160a01b038481166000908152610291602052604090205416156122f95760405162461bcd60e51b8152602060048201526003602482015262261b1960e91b6044820152606401610ccd565b6001600160a01b0384166123355760405162461bcd60e51b815260206004820152600360248201526226189960e91b6044820152606401610ccd565b6001600160a01b0383166123715760405162461bcd60e51b81526020600482015260036024820152624c313360e81b6044820152606401610ccd565b826001600160a01b0316846001600160a01b0316036123b85760405162461bcd60e51b8152602060048201526003602482015262130c4d60ea1b6044820152606401610ccd565b6123c06121e5565b6001600160a01b0316336001600160a01b031614806123e75750336001600160a01b038516145b6124195760405162461bcd60e51b81526020600482015260036024820152624c313560e81b6044820152606401610ccd565b612424846001613ee7565b61242f836001613ee7565b50506001600160a01b039182166000818152610291602090815260408083208054969095166001600160a01b03199687168117909555938252610292815292812080546001810182559082529290209091018054909216179055565b6060609b8054610bf090615694565b6001600160a01b038116600090815260976020526040812054610c87565b6124c0613417565b61030280546001810182556000919091527f552430c2010355dda19e8bae437f75cfb136cb8d667c4c0867367db21eee69b60180546001600160a01b0319166001600160a01b0392909216919091179055565b61251b6137ba565b3361252581613802565b156125425760405162461bcd60e51b8152600401610ccd90615937565b61254b33611c4f565b8211156125805760405162461bcd60e51b81526020600482015260036024820152624c353360e81b6044820152606401610ccd565b6001600160601b038211156125bd5760405162461bcd60e51b8152602060048201526003602482015262130d4d60ea1b6044820152606401610ccd565b6103035434146125f55760405162461bcd60e51b81526020600482015260036024820152624c353560e81b6044820152606401610ccd565b600060405180604001604052806126093390565b6001600160a01b0390811682526001600160601b0386166020909201919091526102f9549192506000916002911663c8f74bb8336040518263ffffffff1660e01b815260040161265991906154a7565b602060405180830381865afa158015612676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269a9190615953565b101580156126ab5750600061030054115b156127195761030080549060006126c1836159d7565b9190505550610300549050816102ff82815481106126e1576126e16157c1565b6000918252602091829020835193909201516001600160601b0316600160a01b026001600160a01b0390931692909217910155612783565b6102ff8054600181810183556000839052845160208601516001600160601b0316600160a01b026001600160a01b03909116177f5a4a1f748f8cfa795b59cdc37192794ee567e6029e925719381be08d7ccaf4ec909201919091559054612780919061584f565b90505b836102fd600082825461279691906157ae565b9091555060019050336001600160a01b031682600080516020615e94833981519152878860006000196040516127cf949392919061596c565b60405180910390a46127e13385613add565b6102fa546040516000916001600160a01b03169034908381818185875af1925050503d806000811461282f576040519150601f19603f3d011682016040523d82523d6000602084013e612834565b606091505b505090508061201b5760405162461bcd60e51b8152602060048201526003602482015262261a9b60e91b6044820152606401610ccd565b612873613417565b61030354614e2010156128985760405162461bcd60e51b8152600401610ccd906159ee565b61030355565b600033816128ac8286613199565b90508381101561290c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610ccd565b61291982868684036132f3565b506001949350505050565b61292c613417565b6102f980546001600160a01b0319166001600160a01b0392909216919091179055565b6129576137ba565b8161296181613802565b1561297e5760405162461bcd60e51b8152600401610ccd90615937565b8161298881613802565b156129a55760405162461bcd60e51b8152600401610ccd90615937565b6001600160a01b0384166129e15760405162461bcd60e51b815260206004820152600360248201526226189b60e91b6044820152606401610ccd565b6001600160a01b038316612a1d5760405162461bcd60e51b81526020600482015260036024820152624c313760e81b6044820152606401610ccd565b612a256121e5565b6001600160a01b0316336001600160a01b03161480612a4c5750336001600160a01b038516145b612a7e5760405162461bcd60e51b815260206004820152600360248201526209862760eb1b6044820152606401610ccd565b6001600160a01b0384811660009081526102916020526040902054811690841614612ad15760405162461bcd60e51b81526020600482015260036024820152624c313960e81b6044820152606401610ccd565b612adc846001613ee7565b612ae7836001613ee7565b60001960005b6001600160a01b03851660009081526102926020526040902054811015612b72576001600160a01b0385811660009081526102926020526040902080549188169183908110612b3e57612b3e6157c1565b6000918252602090912001546001600160a01b031603612b6057809150612b72565b80612b6a81615886565b915050612aed565b506000811215612b8457612b84615a0b565b6001600160a01b0380861660009081526102916020908152604080832080546001600160a01b031916905592871682526102929052208054612bc89060019061584f565b81548110612bd857612bd86157c1565b60009182526020808320909101546001600160a01b0387811684526102929092526040909220805491909216919083908110612c1657612c166157c1565b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918616815261029290915260409020805480612c5c57612c5c615987565b600082815260209020810160001990810180546001600160a01b03191690550190555050505050565b600033610c81818585613610565b612c9b613417565b60006102fe54612ca9611c3f565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612cd491906154a7565b602060405180830381865afa158015612cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d159190615953565b612d1f919061584f565b905060008111612d575760405162461bcd60e51b8152602060048201526003602482015262130d0d60ea1b6044820152606401610ccd565b6114d6612d62611c3f565b82613df0565b612d706137ba565b33612d7a81613802565b15612d975760405162461bcd60e51b8152600401610ccd90615937565b81612da0611c3f565b6001600160a01b03166370a08231336040518263ffffffff1660e01b8152600401612dcb91906154a7565b602060405180830381865afa158015612de8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0c9190615953565b1015612e405760405162461bcd60e51b81526020600482015260036024820152624c343760e81b6044820152606401610ccd565b816102fe6000828254612e5391906157ae565b9091555060009050336001600160a01b0316600019600080516020615e9483398151915285866002600019604051612e8e949392919061596c565b60405180910390a4612ea03383613fbc565b5061193f613d92565b6102f95460405163191ee97760e31b815260009182916002916001600160a01b03169063c8f74bb890612ee09088906004016154a7565b602060405180830381865afa158015612efd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f219190615953565b10612f3157508190506000612fbf565b6000612f4e612f4961028e546001600160a01b031690565b61403d565b90506000612f5c85836140aa565b6102fb54909150600090612f7d90600160a01b900463ffffffff16846140e8565b90506000612f8c606485614114565b612f968385615a21565b612fa091906157d7565b9050612fac8185614142565b9450612fb8858861584f565b9550505050505b9250929050565b6102ff8181548110611a0257600080fd5b60405163106d64cf60e31b8152610290600482015260009073__$3728f51d90da6977d2525dcec632daa0b3$__9063836b267890602401602060405180830381865af415801561302b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190615a38565b6000610c87826001614179565b613064613417565b60006102fc541161309d5760405162461bcd60e51b815260206004820152600360248201526204c36360ec1b6044820152606401610ccd565b6102fc546102fe5410156130d95760405162461bcd60e51b81526020600482015260036024820152624c363160e81b6044820152606401610ccd565b6102fc546102fe60008282546130ef919061584f565b90915550506102fc805460009091556114d66131096121e5565b82611353611c3f565b60008061312b612f4961028e546001600160a01b031690565b9050600061314061313a610fd0565b836140aa565b6102fb5490915060009061316190600160c01b900463ffffffff16846140e8565b90506000613170606485614114565b61317a8385615a21565b61318491906157d7565b90506131908185614142565b94505050505090565b6001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6131cc613417565b614e2063ffffffff821611156131f45760405162461bcd60e51b8152600401610ccd906159ee565b6102fb805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b610302818154811061322c57600080fd5b6000918252602090912001546001600160a01b0316905081565b6000610ff660995490565b613259613417565b60405162461bcd60e51b8152602060048201526002602482015261098760f31b6044820152606401610ccd565b61328e613417565b61271063ffffffff821611156132cc5760405162461bcd60e51b81526020600482015260036024820152624c343160e81b6044820152606401610ccd565b6102fb805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b6001600160a01b0383166133555760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610ccd565b6001600160a01b0382166133b65760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610ccd565b6001600160a01b0383811660008181526098602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b336134206121e5565b6001600160a01b0316146134765760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ccd565b565b600054610100900460ff1661349f5760405162461bcd60e51b8152600401610ccd90615a55565b6134aa8585856146df565b6134b48282614739565b61201b61476a565b600054610100900460ff166134e35760405162461bcd60e51b8152600401610ccd90615a55565b6114d681614791565b600054610100900460ff166135135760405162461bcd60e51b8152600401610ccd90615a55565b61028e80546001600160a01b0319166001600160a01b03831617905560405163433e3bad60e11b815261029060048201526000602482015273__$3728f51d90da6977d2525dcec632daa0b3$__9063867c775a9060440160006040518083038186803b15801561358257600080fd5b505af415801561201b573d6000803e3d6000fd5b60006135a28484613199565b9050600019811461360a57818110156135fd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610ccd565b61360a84848484036132f3565b50505050565b6001600160a01b0383166136745760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610ccd565b6001600160a01b0382166136d65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610ccd565b6136e1838383614833565b6001600160a01b038316600090815260976020526040902054818110156137595760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610ccd565b6001600160a01b038085166000818152609760205260408082208686039055928616808252908390208054860190559151600080516020615e74833981519152906137a79086815260200190565b60405180910390a361360a848484614872565b6137c2611a2d565b156134765760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ccd565b6101935460405163fe575a8760e01b81526000916001600160a01b03169063fe575a87906138349085906004016154a7565b602060405180830381865afa158015613851573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c879190615aa0565b6040516001600160a01b03831660248201526044810182905261188590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614973565b6102c6546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048083019260209291908290030181865afa92505050801561393f575060408051601f3d908101601f1916820190925261393c91810190615ac2565b60015b6139495750601290565b919050565b600080516020615e2d833981519152546001600160a01b031690565b6114d6613417565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156139a55761188583614a48565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156139ff575060408051601f3d908101601f191682019092526139fc91810190615953565b60015b613a625760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610ccd565b600080516020615e2d8339815191528114613ad15760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610ccd565b50611885838383614ae4565b6001600160a01b038216613b3d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610ccd565b613b4982600083614833565b6001600160a01b03821660009081526097602052604090205481811015613bbd5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610ccd565b6001600160a01b0383166000818152609760209081526040808320868603905560998054879003905551858152919291600080516020615e74833981519152910160405180910390a361188583600084614872565b6000613c1e3383613add565b6102c654613c36906001600160a01b03168484613875565b50600192915050565b6001600160a01b038216613c955760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610ccd565b613ca160008383614833565b8060996000828254613cb391906157ae565b90915550506001600160a01b038216600081815260976020908152604080832080548601905551848152600080516020615e74833981519152910160405180910390a361193f60008383614872565b6101605460408051635c975abb60e01b815290516000926001600160a01b031691635c975abb9160048083019260209291908290030181865afa158015613d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190615aa0565b61360a846323b872dd60e01b8585856040516024016138a193929190615ae5565b6000613d9c613112565b9050806102fe5411613dab5750565b6000816102fe54613dbc919061584f565b9050806102fe6000828254613dd1919061584f565b90915550506102fb5461193f906001600160a01b031682611353611c3f565b613df8613417565b60008111613e2e5760405162461bcd60e51b815260206004820152600360248201526204c31360ec1b6044820152606401610ccd565b6040516370a0823160e01b8152829082906001600160a01b038316906370a0823190613e5e9030906004016154a7565b602060405180830381865afa158015613e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9f9190615953565b1015613ed35760405162461bcd60e51b81526020600482015260036024820152624c313160e81b6044820152606401610ccd565b6118856001600160a01b0382163384613875565b6102935460ff1615613ef7575050565b6001600160a01b038216600090815261028f602052604090205464ffffffffff428116911603613f25575050565b6001600160a01b0380831660009081526102916020526040902054168015613f51576118858183613ee7565b6000613f5d8484614179565b90508015613fb357610293805460ff191660011790556000613f7f8583614b09565b610293805460ff19169055905080613fb1576001600160a01b038516600090815261028f602052604090206003018290555b505b61360a84614b60565b60003330810361401a5760405162461bcd60e51b815260206004820152602360248201527f4552433230577261707065723a20777261707065722063616e2774206465706f6044820152621cda5d60ea1b6064820152608401610ccd565b6102c654614033906001600160a01b0316823086613d71565b610c818484613c3f565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561407d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140a19190615ac2565b60ff1692915050565b600060038210156140dc576140c082600661584f565b6140cb90600a615bed565b6140d59084615a21565b9050610c87565b61104b836103e8615a21565b600060038210156140ff576140d5836103e8615a21565b61410a82600a615bed565b61104b9084615a21565b6000600382101561412c576140d583620f4240615a21565b6141378260036157ae565b61410a90600a615bed565b6000600382101561416d5761415882600661584f565b61416390600a615bed565b6140d590846157d7565b61104b6103e8846157d7565b6001600160a01b038216600090815261028f602090815260408083208151608081018352815464ffffffffff16818401908152835180850190945260018301548452600283015463ffffffff168486015260608201939093529182526003015491810191909152816141ea85614cc2565b82515190915064ffffffffff161580614201575080155b1561421157600092505050610c87565b815160200151604051630b27cfb160e31b815260009073__$3728f51d90da6977d2525dcec632daa0b3$__9063593e7d889061425590610290908690600401615bf9565b6040805180830381865af4158015614271573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142959190615c1d565b60405163038255fd60e11b8152610290600482015290915060009073__$3728f51d90da6977d2525dcec632daa0b3$__90630704abfa906024016040805180830381865af41580156142eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061430f9190615c68565b90508460200151955073__$3728f51d90da6977d2525dcec632daa0b3$__634ead0c5384836040518363ffffffff1660e01b8152600401614351929190615c94565b602060405180830381865af415801561436e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143929190615aa0565b6146a357604051633e1e5c5360e11b815260009073__$3728f51d90da6977d2525dcec632daa0b3$__90637c3cb8a6906143d0908790600401615cc8565b6040805180830381865af41580156143ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144109190615c68565b604051630b27cfb160e31b815290915060009073__$3728f51d90da6977d2525dcec632daa0b3$__9063593e7d889061445190610290908690600401615bf9565b6040805180830381865af415801561446d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144919190615c1d565b875151602082015186519293506144bf928c6144ae5760006144b0565b8b5b6144ba908b6157ae565b614d6b565b6144c990896157ae565b97505b81945080935073__$3728f51d90da6977d2525dcec632daa0b3$__634ead0c5386856040518363ffffffff1660e01b815260040161450b929190615c94565b602060405180830381865af4158015614528573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061454c9190615aa0565b61467657604051633e1e5c5360e11b815273__$3728f51d90da6977d2525dcec632daa0b3$__90637c3cb8a690614587908890600401615cc8565b6040805180830381865af41580156145a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145c79190615c68565b604051630b27cfb160e31b815290925073__$3728f51d90da6977d2525dcec632daa0b3$__9063593e7d889061460590610290908690600401615bf9565b6040805180830381865af4158015614621573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146459190615c1d565b90506146658460200151826020015186600001518c6144ae5760006144b0565b61466f90896157ae565b97506144cc565b61469084602001514286600001518c6144ae5760006144b0565b61469a90896157ae565b975050506146d4565b84515182516146c7919042908a6146bb5760006146bd565b895b6144ba90896157ae565b6146d190876157ae565b95505b505050505092915050565b600054610100900460ff166147065760405162461bcd60e51b8152600401610ccd90615a55565b61470e61476a565b61471783614e57565b61471f614e87565b61472882614eb6565b61473181614f00565b61188561476a565b600054610100900460ff166147605760405162461bcd60e51b8152600401610ccd90615a55565b61193f8282614f4a565b600054610100900460ff166134765760405162461bcd60e51b8152600401610ccd90615a55565b600054610100900460ff166147b85760405162461bcd60e51b8152600401610ccd90615a55565b306001600160a01b038216036148105760405162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a2063616e6e6f742073656c66207772617000006044820152606401610ccd565b6102c680546001600160a01b0319166001600160a01b0392909216919091179055565b61483e838383614f8a565b6001600160a01b0383161561485857614858836001613ee7565b6001600160a01b0382161561188557611885826001613ee7565b6001600160a01b038316158061488f57506001600160a01b038216155b156148cf577f980f7e6fb44009001d533a10bc3bd558b4efe22dcb4888bca4767aa93c71ce1f6148bd610fd0565b60405190815260200160405180910390a15b60005b6103025481101561360a5761030281815481106148f1576148f16157c1565b600091825260209091200154604051636e0d037d60e11b81526001600160a01b039091169063dc1a06fa9061492e90879087908790600401615ae5565b600060405180830381600087803b15801561494857600080fd5b505af115801561495c573d6000803e3d6000fd5b50505050808061496b90615886565b9150506148d2565b60006149c8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614feb9092919063ffffffff16565b90508051600014806149e95750808060200190518101906149e99190615aa0565b6118855760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610ccd565b6001600160a01b0381163b614ab55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610ccd565b600080516020615e2d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b614aed83614ffa565b600082511180614afa5750805b156118855761360a838361503a565b6000826001600160a01b03167f05a71d417f891ba4b7a94b48d1b1f4b59b070921cba593b3c72a05a5587a78a9614b3f8561249a565b60408051918252602082018690520160405180910390a2613c368383613c3f565b6001600160a01b038116600090815261028f602052604090819020805464ffffffffff19164264ffffffffff161790555163038255fd60e11b8152610290600482015273__$3728f51d90da6977d2525dcec632daa0b3$__90630704abfa906024016040805180830381865af4158015614bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614c029190615c68565b6001600160a01b038216600090815261028f602090815260408220835160018201559201516002909201805463ffffffff191663ffffffff909316929092179091555b6001600160a01b0382166000908152610292602052604090205481101561193f576001600160a01b0382166000908152610292602052604090208054614cb0919083908110614c9657614c966157c1565b6000918252602090912001546001600160a01b0316614b60565b80614cba81615886565b915050614c45565b6000614ccd8261505f565b614cd790826157ae565b905060005b6001600160a01b03831660009081526102926020526040902054811015614d65576001600160a01b0383166000908152610292602052604090208054614d47919083908110614d2d57614d2d6157c1565b6000918252602090912001546001600160a01b0316614cc2565b614d5190836157ae565b915080614d5d81615886565b915050614cdc565b50919050565b600080614d84612f4961028e546001600160a01b031690565b90506000614da2614d958888615ce5565b64ffffffffff1683614114565b90506000614db46301e1338084614114565b614dbf600185614114565b614dc99084615a21565b614dd391906157d7565b90506000614de58761ffff16856140e8565b90506000614df4600186614114565b614dfe8385615a21565b614e0891906157d7565b90506000614e1688876140aa565b90506000614e25606488614114565b614e2f8484615a21565b614e3991906157d7565b9050614e458188614142565b9750505050505050505b949350505050565b600054610100900460ff16614e7e5760405162461bcd60e51b8152600401610ccd90615a55565b6114d68161506a565b600054610100900460ff16614eae5760405162461bcd60e51b8152600401610ccd90615a55565b6134766150b4565b600054610100900460ff16614edd5760405162461bcd60e51b8152600401610ccd90615a55565b61016080546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16614f275760405162461bcd60e51b8152600401610ccd90615a55565b61019380546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16614f715760405162461bcd60e51b8152600401610ccd90615a55565b609a614f7d8382615d50565b50609b6118858282615d50565b614f926137ba565b82614f9c81613802565b15614fb95760405162461bcd60e51b8152600401610ccd90615937565b82614fc381613802565b15614fe05760405162461bcd60e51b8152600401610ccd90615937565b61201b8585856150e7565b6060614e4f848460008561514f565b61500381614a48565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061104b8383604051806060016040528060278152602001615e4d6027913961522a565b6000610c878261249a565b600054610100900460ff166150915760405162461bcd60e51b8152600401610ccd90615a55565b61012d80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166150db5760405162461bcd60e51b8152600401610ccd90615a55565b60c9805460ff19169055565b6150ef611a2d565b156118855760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610ccd565b6060824710156151b05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610ccd565b600080866001600160a01b031685876040516151cc9190615e10565b60006040518083038185875af1925050503d8060008114615209576040519150601f19603f3d011682016040523d82523d6000602084013e61520e565b606091505b509150915061521f878383876152a2565b979650505050505050565b6060600080856001600160a01b0316856040516152479190615e10565b600060405180830381855af49150503d8060008114615282576040519150601f19603f3d011682016040523d82523d6000602084013e615287565b606091505b5091509150615298868383876152a2565b9695505050505050565b6060831561531157825160000361530a576001600160a01b0385163b61530a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ccd565b5081614e4f565b614e4f83838151156153265781518083602001fd5b8060405162461bcd60e51b8152600401610ccd9190615364565b60005b8381101561535b578181015183820152602001615343565b50506000910152565b6020815260008251806020840152615383816040850160208701615340565b601f01601f19169190910160400192915050565b6001600160a01b03811681146114d657600080fd5b600080604083850312156153bf57600080fd5b82356153ca81615397565b946020939093013593505050565b6000602082840312156153ea57600080fd5b813561104b81615397565b600080600080600060a0868803121561540d57600080fd5b853561541881615397565b9450602086013561542881615397565b9350604086013561543881615397565b9250606086013561544881615397565b9150608086013561545881615397565b809150509295509295909350565b60008060006060848603121561547b57600080fd5b833561548681615397565b9250602084013561549681615397565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b6000602082840312156154cd57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561550d5761550d6154d4565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561553c5761553c6154d4565b604052919050565b600067ffffffffffffffff82111561555e5761555e6154d4565b50601f01601f191660200190565b6000806040838503121561557f57600080fd5b823561558a81615397565b9150602083013567ffffffffffffffff8111156155a657600080fd5b8301601f810185136155b757600080fd5b80356155ca6155c582615544565b615513565b8181528660208385010111156155df57600080fd5b816020840160208301376000602083830101528093505050509250929050565b61ffff811681146114d657600080fd5b60006020828403121561562157600080fd5b813561104b816155ff565b6000806040838503121561563f57600080fd5b823561564a81615397565b9150602083013561565a81615397565b809150509250929050565b63ffffffff811681146114d657600080fd5b60006020828403121561568957600080fd5b813561104b81615665565b600181811c908216806156a857607f821691505b602082108103614d6557634e487b7160e01b600052602260045260246000fd5b6000602082840312156156da57600080fd5b815167ffffffffffffffff8111156156f157600080fd5b8201601f8101841361570257600080fd5b80516157106155c582615544565b81815285602083850101111561572557600080fd5b615736826020830160208601615340565b95945050505050565b6702632b233b4ba3c960c51b815260008251615762816008850160208701615340565b9190910160080192915050565b601360fa1b81526000825161578b816001850160208701615340565b9190910160010192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c8757610c87615798565b634e487b7160e01b600052603260045260246000fd5b6000826157f457634e487b7160e01b600052601260045260246000fd5b500490565b6004811061581757634e487b7160e01b600052602160045260246000fd5b9052565b6001600160601b038581168252841660208201526080810161584060408301856157f9565b82606083015295945050505050565b81810381811115610c8757610c87615798565b6001600160601b0385168152602081018490526080810161584060408301856157f9565b60006001820161589857615898615798565b5060010190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252600290820152614c3960f01b604082015260600190565b60006020828403121561596557600080fd5b5051919050565b848152602081018490526080810161584060408301856157f9565b634e487b7160e01b600052603160045260246000fd5b60208082526003908201526204c34360ec1b604082015260600190565b6000602082840312156159cc57600080fd5b815161104b81615397565b6000816159e6576159e6615798565b506000190190565b60208082526003908201526209870760eb1b604082015260600190565b634e487b7160e01b600052600160045260246000fd5b8082028115828204841417610c8757610c87615798565b600060208284031215615a4a57600080fd5b815161104b816155ff565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615ab257600080fd5b8151801515811461104b57600080fd5b600060208284031215615ad457600080fd5b815160ff8116811461104b57600080fd5b6001600160a01b039384168152919092166020820152604081019190915260600190565b600181815b80851115615b44578160001904821115615b2a57615b2a615798565b80851615615b3757918102915b93841c9390800290615b0e565b509250929050565b600082615b5b57506001610c87565b81615b6857506000610c87565b8160018114615b7e5760028114615b8857615ba4565b6001915050610c87565b60ff841115615b9957615b99615798565b50506001821b610c87565b5060208310610133831016604e8410600b8410161715615bc7575081810a610c87565b615bd18383615b09565b8060001904821115615be557615be5615798565b029392505050565b600061104b8383615b4c565b8281526060810161104b60208301848051825260209081015163ffffffff16910152565b600060408284031215615c2f57600080fd5b615c376154ea565b8251615c42816155ff565b8152602083015164ffffffffff81168114615c5c57600080fd5b60208201529392505050565b600060408284031215615c7a57600080fd5b615c826154ea565b825181526020830151615c5c81615665565b8251815260208084015163ffffffff16908201526080810182516040830152602083015163ffffffff16606083015261104b565b8151815260208083015163ffffffff169082015260408101610c87565b64ffffffffff828116828216039080821115615d0357615d03615798565b5092915050565b601f82111561188557600081815260208120601f850160051c81016020861015615d315750805b601f850160051c820191505b81811015610fc857828155600101615d3d565b815167ffffffffffffffff811115615d6a57615d6a6154d4565b615d7e81615d788454615694565b84615d0a565b602080601f831160018114615db35760008415615d9b5750858301515b600019600386901b1c1916600185901b178555610fc8565b600085815260208120601f198616915b82811015615de257888601518255948401946001909101908401615dc3565b5085821015615e005787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251615e22818460208701615340565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efd58e94604d90293a1c1ad95bfe6a6e6c352c33c5774a4b6b4f4b6f7460da29c5a2646970667358221220796e679a619b27b0c2166aa2b4934a098e55727f912cd99f85a1da2f76dfe77764736f6c63430008120033", "libraries": { "APRHistory": "0x3F0Ff9947550d7Cf26549136552C785446ad4Ac5" }, @@ -1343,7 +1369,7 @@ "author": "Lila Rest (https://lila.rest)", "custom:oz-upgrades-unsafe-allow": "external-library-linking", "custom:security-contact": "security@ledgity.comsecurity@ledgity.com", - "details": "Definitions: - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio). - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees). - Instant: Processed immediately. - Requested: Queued for later processing. - Big Requested: A requested withdrawal exceeding half of the retention rate. - (Withdrawal) queue: An list of all requested withdrawals sorted by priority. - Request ID: The index of a withdrawal request in the queue array. - Retention rate: Maximum fraction of underlying tokens TVL that the contract can retain. - Fees Rate: Percentage of fees applied to successful withdrawals. - Usable underlyings: Amount of underlying tokens that have been deposited through expected ways and are so considered as safe to use by the contract. - Transfers listeners: External contracts listening on L-Tokens transfers. - Fund wallet: Wallet managed by the Ledgity's financial team. - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request processing. Note that words between parenthesis are sometimes omitted for brevity.Security: This contract can safely receive funds immediately after initialization. (i.e., there is no way for funds to be sent to non-owned addresses). It is however recommended to replace ASAP owner and fund wallets by multi-sig wallets.For further details, see \"LToken\" section of whitepaper.", + "details": "Definitions: - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio). - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees). - Instant: Processed immediately. - Request: Queued for later processing. - Big Request: A requested withdrawal exceeding half of the retention rate. - (Withdrawal) queue: A list of all requested withdrawals sorted by priority. - Request ID: The index of a withdrawal request in the queue array. - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain. - Fees Rate: Percentage of fees applied to successful withdrawals. - Usable underlyings: Amount of underlying tokens that have been deposited through expected ways and are so considered safe to use by the contract. - Transfers listeners: External contracts listening on L-Tokens transfers. - Fund wallet: Wallet managed by the Ledgity's financial team. - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request processing. Note that words between parenthesis are sometimes omitted for brevity.Deployment notice: This contract can safely receive funds immediately after initialization. (i.e., there is no way for funds to be sent to non-owned addresses). It is, however, recommended to replace ASAP owner and fund wallets with multi-sig wallets.For further details, see \"LToken\" section of whitepaper.", "events": { "APRChangeEvent(uint16)": { "params": { @@ -1550,7 +1576,7 @@ } }, "requestWithdrawal(uint256)": { - "details": "The sender must attach 0.003 ETH to pre-pay the future processing gas fees paid by the withdrawer wallet.", + "details": "The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees paid by the withdrawer wallet.", "params": { "amount": "The amount L-Tokens to withdraw." } @@ -1586,6 +1612,11 @@ "withdrawer_": "The address of the new withdrawer wallet." } }, + "setWithdrwalFeeInEth(uint256)": { + "params": { + "withdrwalFeeInEth_": "The new withdrawalFee in ETH." + } + }, "startRewardsRedirection(address,address)": { "params": { "from": "The address of the account to redirect rewards from.", @@ -1790,6 +1821,9 @@ "setWithdrawer(address)": { "notice": "Updates the address of the withdrawer wallet." }, + "setWithdrwalFeeInEth(uint256)": { + "notice": "Updates the current withdrawalFeeInETH." + }, "startRewardsRedirection(address,address)": { "notice": "Enables redirection of rewards from one account to another." }, @@ -1831,9 +1865,12 @@ }, "withdrawer()": { "notice": "Holds address of withdrawer wallet (managed by withdrawal server)." + }, + "withdrwalFeeInEth()": { + "notice": "Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet." } }, - "notice": "Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e, investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin. As soon as a wallet holds some L-Tokens, it starts receiving rewards in the form of additional L-Tokens, which are auto-compounded over time.", + "notice": "Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e., investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin. As soon as a wallet holds some L-Tokens, it starts receiving rewards in the form of additional L-Tokens, which are auto-compounded over time.", "version": 1 }, "storageLayout": { @@ -1871,7 +1908,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 2785, + "astId": 2869, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -1879,7 +1916,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 1053, + "astId": 1137, "contract": "contracts/src/LToken.sol:LToken", "label": "_balances", "offset": 0, @@ -1887,7 +1924,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1059, + "astId": 1143, "contract": "contracts/src/LToken.sol:LToken", "label": "_allowances", "offset": 0, @@ -1895,7 +1932,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1061, + "astId": 1145, "contract": "contracts/src/LToken.sol:LToken", "label": "_totalSupply", "offset": 0, @@ -1903,7 +1940,7 @@ "type": "t_uint256" }, { - "astId": 1063, + "astId": 1147, "contract": "contracts/src/LToken.sol:LToken", "label": "_name", "offset": 0, @@ -1911,7 +1948,7 @@ "type": "t_string_storage" }, { - "astId": 1065, + "astId": 1149, "contract": "contracts/src/LToken.sol:LToken", "label": "_symbol", "offset": 0, @@ -1919,7 +1956,7 @@ "type": "t_string_storage" }, { - "astId": 1645, + "astId": 1729, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -1959,15 +1996,15 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 7671, + "astId": 8162, "contract": "contracts/src/LToken.sol:LToken", "label": "_globalOwner", "offset": 0, "slot": "301", - "type": "t_contract(GlobalOwner)4909" + "type": "t_contract(GlobalOwner)4308" }, { - "astId": 7755, + "astId": 8246, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -1975,15 +2012,15 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 7773, + "astId": 8264, "contract": "contracts/src/LToken.sol:LToken", "label": "_globalPause", "offset": 0, "slot": "352", - "type": "t_contract(GlobalPause)4985" + "type": "t_contract(GlobalPause)4384" }, { - "astId": 7832, + "astId": 8323, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -1991,15 +2028,15 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 7846, + "astId": 8337, "contract": "contracts/src/LToken.sol:LToken", "label": "_globalBlacklist", "offset": 0, "slot": "403", - "type": "t_contract(GlobalBlacklist)4862" + "type": "t_contract(GlobalBlacklist)4261" }, { - "astId": 7920, + "astId": 8411, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2007,7 +2044,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 8939, + "astId": 9430, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2015,7 +2052,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 9030, + "astId": 9521, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2023,7 +2060,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 1783, + "astId": 1867, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2031,7 +2068,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 9135, + "astId": 9626, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2039,31 +2076,31 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 7972, + "astId": 8463, "contract": "contracts/src/LToken.sol:LToken", "label": "_invested", "offset": 0, "slot": "654", - "type": "t_contract(IERC20Upgradeable)1724" + "type": "t_contract(IERC20Upgradeable)1808" }, { - "astId": 7978, + "astId": 8469, "contract": "contracts/src/LToken.sol:LToken", "label": "accountsDetails", "offset": 0, "slot": "655", - "type": "t_mapping(t_address,t_struct(AccountDetails)7968_storage)" + "type": "t_mapping(t_address,t_struct(AccountDetails)8459_storage)" }, { - "astId": 7983, + "astId": 8474, "contract": "contracts/src/LToken.sol:LToken", "label": "_aprHistory", "offset": 0, "slot": "656", - "type": "t_array(t_struct(Pack)11985_storage)dyn_storage" + "type": "t_array(t_struct(Pack)9658_storage)dyn_storage" }, { - "astId": 7988, + "astId": 8479, "contract": "contracts/src/LToken.sol:LToken", "label": "rewardsRedirectsFromTo", "offset": 0, @@ -2071,7 +2108,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 7993, + "astId": 8484, "contract": "contracts/src/LToken.sol:LToken", "label": "rewardsRedirectsToFrom", "offset": 0, @@ -2079,7 +2116,7 @@ "type": "t_mapping(t_address,t_array(t_address)dyn_storage)" }, { - "astId": 7996, + "astId": 8487, "contract": "contracts/src/LToken.sol:LToken", "label": "_isClaiming", "offset": 0, @@ -2087,7 +2124,7 @@ "type": "t_bool" }, { - "astId": 8846, + "astId": 9337, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2095,15 +2132,15 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 1797, + "astId": 1881, "contract": "contracts/src/LToken.sol:LToken", "label": "_underlying", "offset": 0, "slot": "710", - "type": "t_contract(IERC20Upgradeable)1724" + "type": "t_contract(IERC20Upgradeable)1808" }, { - "astId": 1976, + "astId": 2060, "contract": "contracts/src/LToken.sol:LToken", "label": "__gap", "offset": 0, @@ -2111,15 +2148,15 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 5045, + "astId": 5572, "contract": "contracts/src/LToken.sol:LToken", "label": "ldyStaking", "offset": 0, "slot": "761", - "type": "t_contract(LDYStaking)4745" + "type": "t_contract(LDYStaking)5504" }, { - "astId": 5048, + "astId": 5575, "contract": "contracts/src/LToken.sol:LToken", "label": "withdrawer", "offset": 0, @@ -2127,7 +2164,7 @@ "type": "t_address_payable" }, { - "astId": 5051, + "astId": 5578, "contract": "contracts/src/LToken.sol:LToken", "label": "fund", "offset": 0, @@ -2135,7 +2172,7 @@ "type": "t_address" }, { - "astId": 5054, + "astId": 5581, "contract": "contracts/src/LToken.sol:LToken", "label": "feesRateUD7x3", "offset": 20, @@ -2143,7 +2180,7 @@ "type": "t_uint32" }, { - "astId": 5057, + "astId": 5584, "contract": "contracts/src/LToken.sol:LToken", "label": "retentionRateUD7x3", "offset": 24, @@ -2151,7 +2188,7 @@ "type": "t_uint32" }, { - "astId": 5060, + "astId": 5587, "contract": "contracts/src/LToken.sol:LToken", "label": "unclaimedFees", "offset": 0, @@ -2159,7 +2196,7 @@ "type": "t_uint256" }, { - "astId": 5063, + "astId": 5590, "contract": "contracts/src/LToken.sol:LToken", "label": "totalQueued", "offset": 0, @@ -2167,7 +2204,7 @@ "type": "t_uint256" }, { - "astId": 5066, + "astId": 5593, "contract": "contracts/src/LToken.sol:LToken", "label": "usableUnderlyings", "offset": 0, @@ -2175,15 +2212,15 @@ "type": "t_uint256" }, { - "astId": 5071, + "astId": 5598, "contract": "contracts/src/LToken.sol:LToken", "label": "withdrawalQueue", "offset": 0, "slot": "767", - "type": "t_array(t_struct(WithdrawalRequest)5028_storage)dyn_storage" + "type": "t_array(t_struct(WithdrawalRequest)5547_storage)dyn_storage" }, { - "astId": 5074, + "astId": 5601, "contract": "contracts/src/LToken.sol:LToken", "label": "withdrawalQueueCursor", "offset": 0, @@ -2191,20 +2228,28 @@ "type": "t_uint256" }, { - "astId": 5079, + "astId": 5606, "contract": "contracts/src/LToken.sol:LToken", "label": "frozenRequests", "offset": 0, "slot": "769", - "type": "t_array(t_struct(WithdrawalRequest)5028_storage)dyn_storage" + "type": "t_array(t_struct(WithdrawalRequest)5547_storage)dyn_storage" }, { - "astId": 5084, + "astId": 5611, "contract": "contracts/src/LToken.sol:LToken", "label": "transfersListeners", "offset": 0, "slot": "770", - "type": "t_array(t_contract(ITransfersListener)11966)dyn_storage" + "type": "t_array(t_contract(ITransfersListener)9639)dyn_storage" + }, + { + "astId": 5614, + "contract": "contracts/src/LToken.sol:LToken", + "label": "withdrwalFeeInEth", + "offset": 0, + "slot": "771", + "type": "t_uint256" } ], "types": { @@ -2224,20 +2269,20 @@ "label": "address[]", "numberOfBytes": "32" }, - "t_array(t_contract(ITransfersListener)11966)dyn_storage": { - "base": "t_contract(ITransfersListener)11966", + "t_array(t_contract(ITransfersListener)9639)dyn_storage": { + "base": "t_contract(ITransfersListener)9639", "encoding": "dynamic_array", "label": "contract ITransfersListener[]", "numberOfBytes": "32" }, - "t_array(t_struct(Pack)11985_storage)dyn_storage": { - "base": "t_struct(Pack)11985_storage", + "t_array(t_struct(Pack)9658_storage)dyn_storage": { + "base": "t_struct(Pack)9658_storage", "encoding": "dynamic_array", "label": "struct APRHistory.Pack[]", "numberOfBytes": "32" }, - "t_array(t_struct(WithdrawalRequest)5028_storage)dyn_storage": { - "base": "t_struct(WithdrawalRequest)5028_storage", + "t_array(t_struct(WithdrawalRequest)5547_storage)dyn_storage": { + "base": "t_struct(WithdrawalRequest)5547_storage", "encoding": "dynamic_array", "label": "struct LToken.WithdrawalRequest[]", "numberOfBytes": "32" @@ -2277,32 +2322,32 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(GlobalBlacklist)4862": { + "t_contract(GlobalBlacklist)4261": { "encoding": "inplace", "label": "contract GlobalBlacklist", "numberOfBytes": "20" }, - "t_contract(GlobalOwner)4909": { + "t_contract(GlobalOwner)4308": { "encoding": "inplace", "label": "contract GlobalOwner", "numberOfBytes": "20" }, - "t_contract(GlobalPause)4985": { + "t_contract(GlobalPause)4384": { "encoding": "inplace", "label": "contract GlobalPause", "numberOfBytes": "20" }, - "t_contract(IERC20Upgradeable)1724": { + "t_contract(IERC20Upgradeable)1808": { "encoding": "inplace", "label": "contract IERC20Upgradeable", "numberOfBytes": "20" }, - "t_contract(ITransfersListener)11966": { + "t_contract(ITransfersListener)9639": { "encoding": "inplace", "label": "contract ITransfersListener", "numberOfBytes": "20" }, - "t_contract(LDYStaking)4745": { + "t_contract(LDYStaking)5504": { "encoding": "inplace", "label": "contract LDYStaking", "numberOfBytes": "20" @@ -2328,12 +2373,12 @@ "numberOfBytes": "32", "value": "t_mapping(t_address,t_uint256)" }, - "t_mapping(t_address,t_struct(AccountDetails)7968_storage)": { + "t_mapping(t_address,t_struct(AccountDetails)8459_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct InvestUpgradeable.AccountDetails)", "numberOfBytes": "32", - "value": "t_struct(AccountDetails)7968_storage" + "value": "t_struct(AccountDetails)8459_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2347,20 +2392,20 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(AccountDetails)7968_storage": { + "t_struct(AccountDetails)8459_storage": { "encoding": "inplace", "label": "struct InvestUpgradeable.AccountDetails", "members": [ { - "astId": 7965, + "astId": 8456, "contract": "contracts/src/LToken.sol:LToken", "label": "period", "offset": 0, "slot": "0", - "type": "t_struct(InvestmentPeriod)7962_storage" + "type": "t_struct(InvestmentPeriod)8453_storage" }, { - "astId": 7967, + "astId": 8458, "contract": "contracts/src/LToken.sol:LToken", "label": "virtualBalance", "offset": 0, @@ -2370,12 +2415,12 @@ ], "numberOfBytes": "128" }, - "t_struct(InvestmentPeriod)7962_storage": { + "t_struct(InvestmentPeriod)8453_storage": { "encoding": "inplace", "label": "struct InvestUpgradeable.InvestmentPeriod", "members": [ { - "astId": 7958, + "astId": 8449, "contract": "contracts/src/LToken.sol:LToken", "label": "timestamp", "offset": 0, @@ -2383,22 +2428,22 @@ "type": "t_uint40" }, { - "astId": 7961, + "astId": 8452, "contract": "contracts/src/LToken.sol:LToken", "label": "ref", "offset": 0, "slot": "1", - "type": "t_struct(Reference)11990_storage" + "type": "t_struct(Reference)9663_storage" } ], "numberOfBytes": "96" }, - "t_struct(Pack)11985_storage": { + "t_struct(Pack)9658_storage": { "encoding": "inplace", "label": "struct APRHistory.Pack", "members": [ { - "astId": 11978, + "astId": 9651, "contract": "contracts/src/LToken.sol:LToken", "label": "aprsUD7x3", "offset": 0, @@ -2406,7 +2451,7 @@ "type": "t_array(t_uint16)4_storage" }, { - "astId": 11982, + "astId": 9655, "contract": "contracts/src/LToken.sol:LToken", "label": "timestamps", "offset": 0, @@ -2414,7 +2459,7 @@ "type": "t_array(t_uint40)4_storage" }, { - "astId": 11984, + "astId": 9657, "contract": "contracts/src/LToken.sol:LToken", "label": "cursor", "offset": 0, @@ -2424,12 +2469,12 @@ ], "numberOfBytes": "96" }, - "t_struct(Reference)11990_storage": { + "t_struct(Reference)9663_storage": { "encoding": "inplace", "label": "struct APRHistory.Reference", "members": [ { - "astId": 11987, + "astId": 9660, "contract": "contracts/src/LToken.sol:LToken", "label": "packIndex", "offset": 0, @@ -2437,7 +2482,7 @@ "type": "t_uint256" }, { - "astId": 11989, + "astId": 9662, "contract": "contracts/src/LToken.sol:LToken", "label": "cursorIndex", "offset": 0, @@ -2447,12 +2492,12 @@ ], "numberOfBytes": "64" }, - "t_struct(WithdrawalRequest)5028_storage": { + "t_struct(WithdrawalRequest)5547_storage": { "encoding": "inplace", "label": "struct LToken.WithdrawalRequest", "members": [ { - "astId": 5025, + "astId": 5544, "contract": "contracts/src/LToken.sol:LToken", "label": "account", "offset": 0, @@ -2460,7 +2505,7 @@ "type": "t_address" }, { - "astId": 5027, + "astId": 5546, "contract": "contracts/src/LToken.sol:LToken", "label": "amount", "offset": 20, diff --git a/contracts/hardhat/deployments/arbitrum/solcInputs/763174e07eec40e5a74770adce214c49.json b/contracts/hardhat/deployments/arbitrum/solcInputs/763174e07eec40e5a74770adce214c49.json new file mode 100644 index 00000000..6a93722f --- /dev/null +++ b/contracts/hardhat/deployments/arbitrum/solcInputs/763174e07eec40e5a74770adce214c49.json @@ -0,0 +1,165 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeTo(address newImplementation) public virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../../../security/PausableUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract unpausable.\n */\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\n function __ERC20Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __ERC20Pausable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Wrapper.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../utils/SafeERC20Upgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of the ERC20 token contract to support token wrapping.\n *\n * Users can deposit and withdraw \"underlying tokens\" and receive a matching number of \"wrapped tokens\". This is useful\n * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the\n * wrapping of an existing \"basic\" ERC20 into a governance token.\n *\n * _Available since v4.2._\n *\n * @custom:storage-size 51\n */\nabstract contract ERC20WrapperUpgradeable is Initializable, ERC20Upgradeable {\n IERC20Upgradeable private _underlying;\n\n function __ERC20Wrapper_init(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n __ERC20Wrapper_init_unchained(underlyingToken);\n }\n\n function __ERC20Wrapper_init_unchained(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n require(underlyingToken != this, \"ERC20Wrapper: cannot self wrap\");\n _underlying = underlyingToken;\n }\n\n /**\n * @dev See {ERC20-decimals}.\n */\n function decimals() public view virtual override returns (uint8) {\n try IERC20MetadataUpgradeable(address(_underlying)).decimals() returns (uint8 value) {\n return value;\n } catch {\n return super.decimals();\n }\n }\n\n /**\n * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\n */\n function underlying() public view returns (IERC20Upgradeable) {\n return _underlying;\n }\n\n /**\n * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\n */\n function depositFor(address account, uint256 amount) public virtual returns (bool) {\n address sender = _msgSender();\n require(sender != address(this), \"ERC20Wrapper: wrapper can't deposit\");\n SafeERC20Upgradeable.safeTransferFrom(_underlying, sender, address(this), amount);\n _mint(account, amount);\n return true;\n }\n\n /**\n * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\n */\n function withdrawTo(address account, uint256 amount) public virtual returns (bool) {\n _burn(_msgSender(), amount);\n SafeERC20Upgradeable.safeTransfer(_underlying, account, amount);\n return true;\n }\n\n /**\n * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal\n * function that can be exposed with access control if desired.\n */\n function _recover(address account) internal virtual returns (uint256) {\n uint256 value = _underlying.balanceOf(address(this)) - totalSupply();\n _mint(account, value);\n return value;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable2Step.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "contracts/src/abstracts/base/BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"../GlobalOwnableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"../GlobalRestrictableUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../RecoverableUpgradeable.sol\";\n\n/**\n * @title BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract acts as a base for numerous contracts in this codebase,\n * minimizing code repetition and enhancing readability and maintainability.\n *\n * @dev For further details, see \"Base\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract BaseUpgradeable is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n GlobalPausableUpgradeable,\n GlobalRestrictableUpgradeable,\n RecoverableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_\n ) internal onlyInitializing {\n __UUPSUpgradeable_init();\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n __Recoverable_init_unchained();\n }\n\n function __Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/base/ERC20BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./BaseUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\n\n/**\n * @title ERC20BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract is an extension of BaseUpgradeable intended to be used\n * as a base for ERC20 tokens contracts.\n *\n * @dev For further details, see \"ERC20BaseUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract ERC20BaseUpgradeable is\n ERC20Upgradeable,\n BaseUpgradeable,\n ERC20PausableUpgradeable\n{\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param name_ The display name of the token.\n * @param symbol_ The symbol of the token.\n */\n function __ERC20Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n string memory name_,\n string memory symbol_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __ERC20_init(name_, symbol_);\n __ERC20Pausable_init_unchained();\n }\n\n function __ERC20Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and PausableUpgradeable parent contracts.\n * The GlobalPausableUpgradeable version is preferred because it checks the pause\n * state from the GlobalPause contract.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, PausableUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @dev Required override of _beforeTokenTransfer() which is implemented by both\n * ERC20PausableUpgradeable and ERC20Upgradeable parent contracts.\n * The ERC20PausableUpgradeable version is preferred because it also checks that\n * the contract is not paused before allowing the transfer.\n * @inheritdoc ERC20PausableUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n )\n internal\n virtual\n override(ERC20PausableUpgradeable, ERC20Upgradeable)\n whenNotPaused\n notBlacklisted(from)\n notBlacklisted(to)\n {\n ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalOwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {GlobalOwner} from \"../GlobalOwner.sol\";\n\n/**\n * @title GlobalOwnableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\n * contract (see GlobalOwner.sol). This design facilitates centralized management\n * of ownership for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalOwner state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalOwnableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\n /**\n * @notice The GlobalOwner contract the ownership will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalOwner private _globalOwner;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init_unchained(globalOwner_);\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\n // the initial _owner value, calling it would have no effect.\n }\n\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\n _globalOwner = GlobalOwner(globalOwner_);\n }\n\n /**\n * @notice Retrieves the address of GlobalOwner contract.\n * @return The address of the GlobalOwner contract.\n */\n function globalOwner() public view returns (address) {\n return address(_globalOwner);\n }\n\n /**\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\n * from the GlobalOwner contract instead.\n * @return The address of the owner\n */\n function owner() public view override returns (address) {\n return _globalOwner.owner();\n }\n\n /**\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function transferOwnership(address newOwner) public view override onlyOwner {\n newOwner; // Silence unused variable compiler warning\n revert(\"L8\");\n }\n\n /**\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function renounceOwnership() public view override onlyOwner {\n revert(\"L65\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalPause} from \"../GlobalPause.sol\";\n\n/**\n * @title GlobalPausableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a pause state from the specified GlobalPause\n * contract (see GlobalPause.sol). This design facilitates centralized management of\n * pause state for all the Ledgity Yield contracts.\n *\n * @dev Security measure\n * The _globalPause state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalPausableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\n /**\n * @notice The GlobalPause contract the pause state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalPause private _globalPause;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalPause_ The address of the GlobalPause contract.\n */\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n }\n\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\n _globalPause = GlobalPause(globalPause_);\n }\n\n /**\n * @notice Retrieves the address of GlobalPause contract.\n * @return The address of the GlobalPause contract.\n */\n function globalPause() public view returns (address) {\n return address(_globalPause);\n }\n\n /**\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\n * from the GlobalPause contract instead.\n * @return Whether the contract is paused or not.\n */\n function paused() public view virtual override returns (bool) {\n return _globalPause.paused();\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalRestrictableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalBlacklist} from \"../GlobalBlacklist.sol\";\n\n/**\n * @title GlobalRestrictableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a blacklist state from the specified\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\n * centralized management of a blacklist for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalBlacklist state must be set at initialization time and, for evident\n * security reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalRestrictableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalRestrictableUpgradeable is Initializable {\n /**\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalBlacklist private _globalBlacklist;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n }\n\n function __GlobalRestrictable_init_unchained(\n address globalBlacklist_\n ) internal onlyInitializing {\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\n }\n\n /**\n * @notice Retrieves the address of GlobalBlacklist contract.\n * @return The address of the GlobalBlacklist contract.\n */\n function globalBlacklist() public view returns (address) {\n return address(_globalBlacklist);\n }\n\n /**\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n */\n modifier notBlacklisted(address account) {\n require(isBlacklisted(account) == false, \"L9\");\n _;\n }\n\n /**\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n * @return Whether the account is blacklisted.\n */\n function isBlacklisted(address account) internal view returns (bool) {\n return _globalBlacklist.isBlacklisted(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/InvestUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"./GlobalPausableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"./GlobalRestrictableUpgradeable.sol\";\nimport \"./base/BaseUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../abstracts/RecoverableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {APRHistory as APRH} from \"../libs/APRHistory.sol\";\nimport {SUD} from \"../libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title InvestUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with utilities to manage an invested token,\n * users' investment periods, rewards calculations, virtual balances, and auto-compounding.\n *\n * @dev Intuition:\n * This contract primarily exists for code splitting and reusability. It unburdens the\n * LToken contract code, making it easier to understand and maintain.\n *\n * This contract is generic because it may be used in the LDYStaking contract in the future.\n *\n * @dev Definitions:\n * - Investment: The act of depositing or investing tokens into the contract.\n * - Investment period: Time between the last invested amount change and the present.\n * - Virtual balance: Temporary storage for account rewards, used when those can't be\n * distributed between investment periods.\n * - Rewards redirection: Mechanism allowing an account to redirect its rewards to another.\n *\n * @dev Derived contract must:\n * - Set invested token during initialization\n * - Implement _investmentOf() function\n * - (optionally) Implement _distributeRewards() function\n *\n * @dev For further details, see \"InvestmentUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract InvestUpgradeable is BaseUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using APRH for APRH.Pack[];\n\n /**\n * @notice Represents an account's investment period.\n * @param timestamp The timestamp of the most recent rewards distribution.\n * @param ref The reference of the last APR checkpoint at that timestamp.\n */\n struct InvestmentPeriod {\n uint40 timestamp; // Supports dates up to 20/02/36812\n APRH.Reference ref;\n }\n\n /**\n * @notice Represents the investment details of an account.\n * @param period The current investment period of the account.\n * @param virtualBalance May hold a part of account rewards until they are claimed.\n */\n struct AccountDetails {\n InvestmentPeriod period;\n uint256 virtualBalance;\n }\n\n /// @notice Holds a reference to the invested token's contract.\n IERC20Upgradeable private _invested;\n\n /// @notice Holds investment details of each account.\n mapping(address => AccountDetails) internal accountsDetails;\n\n /// @notice Holds an history of the APR value over time (see APRHistory.sol).\n APRH.Pack[] private _aprHistory;\n\n /// @notice Holds active rewards redirections in both from->to and to->from[] ways.\n mapping(address => address) public rewardsRedirectsFromTo;\n mapping(address => address[]) public rewardsRedirectsToFrom;\n\n /// @notice Is used to prevent infinite loop in _beforeInvestmentChange().\n bool private _isClaiming;\n\n /**\n * @notice Emitted to inform listeners about a change in the APR's value.\n * @param newAPRUD7x3 The new APR in UD7x3 format.\n */\n event APRChangeEvent(uint16 newAPRUD7x3);\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param invested_ The address of the invested token contract.\n */\n function __Invest_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address invested_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __Invest_init_unchained(invested_);\n }\n\n function __Invest_init_unchained(address invested_) internal onlyInitializing {\n // Set invested token\n _invested = IERC20Upgradeable(invested_);\n\n // Define initial APR to 0%. This would prevent getAPR() from reverting because\n // of an empty APR history\n _aprHistory.setAPR(0);\n }\n\n /**\n * @notice Retrieves the reference to the invested token contract.\n * @return The reference to the invested token contract.\n */\n function invested() public view returns (IERC20Upgradeable) {\n return _invested;\n }\n\n /**\n * @notice Updates the investment APR. Restricted to owner.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(uint16 aprUD7x3) public onlyOwner {\n _aprHistory.setAPR(aprUD7x3);\n emit APRChangeEvent(aprUD7x3);\n }\n\n /**\n * @notice Retrieves the most recently set APR.\n * @return The current APR in UD7x3 format.\n */\n function getAPR() public view returns (uint16) {\n return _aprHistory.getAPR();\n }\n\n /**\n * @notice Enables redirection of rewards from one account to another.\n * @param from The address of the account to redirect rewards from.\n * @param to The address of the account to redirect rewards to.\n */\n function startRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure the address is not already redirecting rewards\n require(rewardsRedirectsFromTo[from] == address(0), \"L62\");\n\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L12\");\n require(to != address(0), \"L13\");\n\n // Ensure 'from' and 'to' addresses are distinct\n require(from != to, \"L14\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L15\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Activate rewards redirection\n rewardsRedirectsFromTo[from] = to;\n rewardsRedirectsToFrom[to].push(from);\n }\n\n /**\n * @notice Disable an active rewards redirection.\n * @param from The address of the account to stop redirecting rewards from.\n * @param to The address of the account to stop redirecting rewards to.\n */\n function stopRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L16\");\n require(to != address(0), \"L17\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L18\");\n\n // Ensure a rewards redirection was active\n require(rewardsRedirectsFromTo[from] == to, \"L19\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Retrieve 'from' index in the redirection array of 'to'\n int256 fromIndex = -1;\n for (uint256 i = 0; i < rewardsRedirectsToFrom[to].length; i++) {\n if (rewardsRedirectsToFrom[to][i] == from) {\n fromIndex = int256(i);\n break;\n }\n }\n\n // fromIndex should never be -1 at this point\n assert(fromIndex >= 0);\n\n // Deactivate rewards redirection\n rewardsRedirectsFromTo[from] = address(0);\n rewardsRedirectsToFrom[to][uint256(fromIndex)] = rewardsRedirectsToFrom[to][\n rewardsRedirectsToFrom[to].length - 1\n ];\n rewardsRedirectsToFrom[to].pop();\n }\n\n /**\n * @notice Retrieves the total amount of tokens invested by the given account.\n * @dev Derived contracts must implement this function.\n * @param account The account to get the investment of.\n * @return The total amount of tokens invested by the given account.\n */\n function _investmentOf(address account) internal view virtual returns (uint256);\n\n /**\n * @notice Distributes a specified amount of rewards to a given account.\n * @dev Derived contracts may optionally implement this function.\n * @dev Implementations must return true to indicate a successful distribution, and\n * false otherwise. If it returns false, the rewards will be added to the account's\n * virtual balance, in order to be claimed later.\n * @param account The account to claim the rewards of.\n * @param amount The amount of rewards to claim.\n * @return Whether the rewards distribution was successfull.\n */\n function _distributeRewards(address account, uint256 amount) internal virtual returns (bool) {\n account; // Silence unused variables warning\n amount;\n return false;\n }\n\n /**\n * @notice Computes the rewards accrued over a specified period of time, based on a\n * given APR and amount of invested tokens.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param beginTimestamp The moment the period commenced.\n * @param endTimestamp The moment the period concluded.\n * @param aprUD7x3 The APR during this period, in UD7x3 format.\n * @param investedAmount The amount of tokens deposited/invested during the period.\n * @return The amount of rewards generated during the period.\n */\n function _calculatePeriodRewards(\n uint40 beginTimestamp,\n uint40 endTimestamp,\n uint16 aprUD7x3,\n uint256 investedAmount\n ) internal view returns (uint256) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Compute the number of elapsed years\n uint256 elapsedTimeSUD = SUD.fromInt(endTimestamp - beginTimestamp, d);\n uint256 elapsedYearsSUD = (elapsedTimeSUD * SUD.fromInt(1, d)) / SUD.fromInt(365 days, d);\n\n // Compute the growth in invested amount (thanks to rewards)\n uint256 aprSUD = SUD.fromRate(aprUD7x3, d);\n uint256 growthSUD = (elapsedYearsSUD * aprSUD) / SUD.fromInt(1, d);\n\n // Compute and return the rewards\n uint256 investedAmountSUD = SUD.fromAmount(investedAmount, d);\n uint256 rewardsSUD = (investedAmountSUD * growthSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(rewardsSUD, d);\n }\n\n /**\n * @notice Computes the sum of given account's invested amount, plus invested amount\n * of all accounts that recursively redirect rewards to this account.\n * @param account The account to calculate the deep investment of.\n * @return deepInvestedAmount The deep invested amount.\n */\n function _deepInvestmentOf(address account) internal view returns (uint256 deepInvestedAmount) {\n // Consider account's direct investment\n deepInvestedAmount += _investmentOf(account);\n\n // But also the deep investments of all accounts redirecting rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n deepInvestedAmount += _deepInvestmentOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Computes the amount of unclaimed/undistributed rewards of a given account.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param account The account to calculate the unclaimed rewards of.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n * @return rewards The amount of unclaimed/undistributed rewards of the given account.\n */\n function _rewardsOf(\n address account,\n bool autocompound\n ) internal view returns (uint256 rewards) {\n // Retrieve account's investment details\n AccountDetails memory details = accountsDetails[account];\n\n // Retrieve account's deep invested amount\n uint256 investedAmount = _deepInvestmentOf(account);\n\n // Return 0 if the account has never invested or has no invested amount\n if (details.period.timestamp == 0 || investedAmount == 0) return 0;\n\n // Retrieve reference and data of APR checkpoint at which started investment period\n APRH.Reference memory currRef = details.period.ref;\n APRH.CheckpointData memory currCheckpoint = _aprHistory.getDataFromReference(currRef);\n\n // Retrieve reference of latest APR checkpoint\n APRH.Reference memory latestRef = _aprHistory.getLatestReference();\n\n // 1) Fill rewards with virtual balance (rewards not claimed/distributed yet)\n // See \"InvestUpgradeable > Yield calculation > 1)\" section of the whitepaper\n rewards = details.virtualBalance;\n\n // If start checkpoint is not the latest one\n if (!APRH.eq(currRef, latestRef)) {\n // Retrieve reference and data of APR checkpoint that comes after start checkpoint\n APRH.Reference memory nextRef = APRH.incrementReference(currRef);\n APRH.CheckpointData memory nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // 2) Calculate rewards from investment period start to next checkpoint\n // See \"InvestUpgradeable > Yield calculation > 2)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n\n // 3) Calculate rewards for each crossed pair of checkpoints\n // See \"InvestUpgradeable > Yield calculation > 3)\" section of the whitepaper\n while (true) {\n // Set next checkpoint as the current one\n currRef = nextRef;\n currCheckpoint = nextCheckpoint;\n\n // Break if current checkpoint is the latest one\n if (APRH.eq(currRef, latestRef)) break;\n\n // Else, retrieve the new next checkpoint\n nextRef = APRH.incrementReference(currRef);\n nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // Calculate rewards between the current pair of checkpoints\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n\n // 4) Calculate rewards from the latest checkpoint to now\n // See \"InvestUpgradeable > Yield calculation > 4)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n } else {\n // 2.bis) Calculate rewards from investment period start to now\n // See \"InvestUpgradeable > Yield calculation > 2.bis)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n }\n\n /**\n * @notice Recursively resets the investment period of the specified account and of\n * all accounts that directly or indirectly redirect rewards to this account.\n * @param account The account to deeply reset the investment period of.\n */\n function _deepResetInvestmentPeriodOf(address account) internal {\n // Reset account investment period timestamp and APR checkpoint to latest ones\n accountsDetails[account].period.timestamp = uint40(block.timestamp);\n accountsDetails[account].period.ref = _aprHistory.getLatestReference();\n\n // Also reset the ones of all accounts that recursively redirect rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n _deepResetInvestmentPeriodOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Hook to be invoked before the invested amount of an account changes. It\n * ensures that rewards are distributed and that account's investment period is reset.\n * @param account The account whose invested amount is going to change.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n */\n function _beforeInvestmentChange(address account, bool autocompound) internal {\n // This hook is called inside LToken._beforeTokenTransfer() and as new tokens are\n // minted in LToken._distributeRewards(), this guards against infinite loop.\n if (_isClaiming) return;\n\n // LToken._beforeTokenTransfer() calls this hook for both involved addresses.\n // As first call will treat both addresses, the second call would be redundant.\n // Therefore, we skip accounts already processed in this block to save up some gas.\n if (accountsDetails[account].period.timestamp == uint40(block.timestamp)) return;\n\n // If account redirects its rewards\n address redirectRewardsTo = rewardsRedirectsFromTo[account];\n if (redirectRewardsTo != address(0)) {\n // Call hook on redirection target (this will indirectly reset the investment\n // of this source account) and return\n _beforeInvestmentChange(redirectRewardsTo, autocompound);\n return;\n }\n\n // Else, compute account's undistributed/unclaimed rewards\n uint256 rewards = _rewardsOf(account, autocompound);\n\n // If there are some rewards\n if (rewards > 0) {\n // Try to distribute rewards to account\n _isClaiming = true;\n bool distributed = _distributeRewards(account, rewards);\n _isClaiming = false;\n\n // If rewards have not been distributed, accumulate them in account's virtual balance\n if (!distributed) accountsDetails[account].virtualBalance = rewards;\n }\n\n // Finally, deeply reset investment period of the account\n _deepResetInvestmentPeriodOf(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/RecoverableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Conracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title RecoverableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with helper functions allowing the recovery of\n * assets accidentally sent to them.\n *\n * @dev Where are utilities Ether, ERC721, etc.?\n * This abstract contract currently supports only ERC20 tokens. Derived contracts\n * in this codebase currently do not implement the necessary functions to receive Ether\n * or ERC721/ERC1155 tokens, so no recovery functions are provided for these assets.\n *\n * @dev For further details, see \"RecoverableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init(globalOwner_);\n __Recoverable_init_unchained();\n }\n\n function __Recoverable_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Recovers a specified amount of a given token address. Will fail if the\n * contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\n // Ensure the specified amount is not zero\n require(amount > 0, \"L10\");\n\n // Create a reference to token's contract\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\n\n // Ensure there is enough token to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L11\");\n\n // Transfer the recovered token amount to the sender\n tokenContract.safeTransfer(_msgSender(), amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/GlobalBlacklist.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalBlacklist\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global mapping of blacklisted accounts shared by all contracts of the\n * Ledgity Yield codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\n * and getter functions to easily check against this global blacklist.\n *\n * @dev For further details, see \"GlobalBlacklist\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\n /**\n * @notice Mapping of accounts to their blacklist status.\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\n */\n mapping(address => bool) private _list;\n\n /// @dev Emitted when `account` is blacklisted.\n event Blacklisted(address account);\n\n /// @dev Emitted when `account` is unblacklisted.\n event Unblacklisted(address account);\n\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @notice Adds a given account to the blacklist.\n * @param account The account's address to be blacklisted.\n */\n function blacklist(address account) external onlyOwner {\n require(account != address(0), \"L20\");\n _list[account] = true;\n emit Blacklisted(account);\n }\n\n /**\n * @notice Removes a given account from the blacklist.\n * @param account The account's address to be un-blacklisted.\n */\n function unBlacklist(address account) external onlyOwner {\n _list[account] = false;\n emit Unblacklisted(account);\n }\n\n /**\n * @notice Checks whether a given account is blacklisted.\n * @param account Address of the account to check.\n * @return 'true' if the account is blacklisted, 'false' otherwise\n */\n function isBlacklisted(address account) external view returns (bool) {\n // Gas optimization: Avoid accessing storage if account is the zero address\n // (e.g, during a mint or a burn of tokens)\n if (account == address(0)) return false;\n\n // Else, return current account's blacklist status\n return _list[account];\n }\n}\n" + }, + "contracts/src/GlobalOwner.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {Ownable2StepUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\n/**\n * @title GlobalOwner\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds the address of a global owner account shared by all contracts of the\n * Ledgity Yield's codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\n * owner() function that retrieves the owner's address from this contract instead.\n *\n * @dev For further details, see \"GlobalOwner\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n */\n function initialize() public initializer {\n __Ownable2Step_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n}\n" + }, + "contracts/src/GlobalPause.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalPause\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global pause state shared by all contracts of the Ledgity Yield\n * codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\n * paused() function that retrieves the pause state from this contract instead.\n *\n * @dev For further details, see \"GlobalPause\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalPause is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n PausableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\n * but restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n}\n" + }, + "contracts/src/interfaces/ITransfersListener.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\ninterface ITransfersListener {\n function onLTokenTransfer(address from, address to, uint256 amount) external;\n}\n" + }, + "contracts/src/LDYStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {BaseUpgradeable} from \"./abstracts/base/BaseUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title LDYStaking\n * @custom:security-contact security@ledgity.com\n *\n * @dev This contract implements tierOf() function from LDYStaking as it's the only\n * one the LToken contract relies on.\n *\n * @custom:security-contact security@ledgity.com\n */\ncontract LDYStaking is BaseUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Represents a user staking info in array.\n * @param stakedAmount Amount of the stake.\n * @param unStakeAt Unstake at.\n * @param duration Staking period in seconds.\n * @param rewardPerTokenPaid Reward per token paid.\n * @param rewards Rewards to be claimed.\n */\n struct StakingInfo {\n uint256 stakedAmount;\n uint256 unStakeAt;\n uint256 duration;\n uint256 rewardPerTokenPaid;\n uint256 rewards;\n }\n\n /**\n * @notice Represent duration and multiplier per each stake option.\n * @param duration Staking period in seconds.\n * @param multiplier Token weight\n */\n struct StakeDurationInfo {\n uint256 duration;\n uint256 multiplier;\n }\n\n /// @notice Decimals of multiplier\n uint256 public constant MULTIPLIER_BASIS = 1e4;\n\n /// @notice Stake and Reward token.\n IERC20Upgradeable public stakeRewardToken;\n\n /// @notice Minimal stake duration for perks.\n uint256 public stakeDurationForPerks;\n\n /// @notice Minimal stake amount for perks.\n uint256 public stakeAmountForPerks;\n\n /// @notice Stake durations info array.\n StakeDurationInfo[] public stakeDurationInfos;\n\n /// @notice Duration of the rewards (in seconds).\n uint256 public rewardsDuration;\n\n /// @notice Timestamp of when the rewards finish.\n uint256 public finishAt;\n\n /// @notice Timestamp of the reward updated.\n uint256 public lastUpdateTime;\n\n /// @notice Reward per second(total rewards / duration).\n uint256 public rewardRatePerSec;\n\n /// @notice Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\n uint256 public rewardPerTokenStored;\n\n /// @notice Total staked amounts.\n uint256 public totalStaked;\n\n // Total staked amounts with multiplier applied\n uint256 public totalWeightedStake;\n\n /// @notice User stakingInfo map, user address => array of the staking info\n mapping(address => StakingInfo[]) public userStakingInfo;\n\n /// @notice Total rewards amount.\n uint256 public totalRewards;\n\n /**\n * @notice Emitted when users stake token\n * @param user User address\n * @param stakeIndex Latest index of user staking pool\n * @param amount Staked amount\n */\n event Staked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users unstake token\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param amount Staked amount\n */\n event Unstaked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users claim rewards\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param reward Reward token amount\n */\n event RewardPaid(address indexed user, uint256 stakeIndex, uint256 reward);\n\n /**\n * @notice Emitted when admin add rewards.\n * @param rewardAmount Reward amount added by admin.\n * @param rewardPerSec RewardRatePerSec updated.\n */\n event NotifiedRewardAmount(uint256 rewardAmount, uint256 rewardPerSec);\n\n /**\n * @notice Holds a mapping of addresses that default to the highest staking tier.\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\n */\n mapping(address => bool) public highTierAccounts;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\n * @dev This function is intended for setting initial values for the contract's state variables.\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param stakeRewardToken_ The address of stake and reward token(LDY token).\n * @param stakeDurationInfos_ Available Staking Durations.\n * @param stakeDurationForPerks_ Minimal staking duration for perks.\n * @param stakeAmountForPerks_ Minimal staking amount for perks.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address stakeRewardToken_,\n StakeDurationInfo[] memory stakeDurationInfos_,\n uint256 stakeDurationForPerks_,\n uint256 stakeAmountForPerks_\n ) public initializer {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n stakeRewardToken = IERC20Upgradeable(stakeRewardToken_);\n uint stakeDurationInfosLength = stakeDurationInfos_.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n stakeDurationInfos.push(stakeDurationInfos_[i]);\n }\n stakeDurationForPerks = stakeDurationForPerks_;\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n // --------------------\n // MUTATIVE FUNCTIONS\n // --------------------\n\n /**\n * @notice Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\n * @dev Emits a `Staked` event upon successful staking.\n * @param amount The amount of tokens to stake.\n * @param stakeDurationIndex The Index of stakeDurationInfos array.\n */\n function stake(\n uint256 amount,\n uint8 stakeDurationIndex\n ) external nonReentrant whenNotPaused notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(stakeDurationIndex <= stakeDurationInfos.length - 1, \"Invalid staking period\");\n\n _updateReward(address(0), 0);\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[stakeDurationIndex];\n StakingInfo memory stakingInfo = StakingInfo({\n stakedAmount: amount,\n unStakeAt: block.timestamp + stakeDurationInfo.duration,\n duration: stakeDurationInfo.duration,\n rewardPerTokenPaid: rewardPerTokenStored,\n rewards: 0\n });\n\n // check whether account is eligible for benefit from the protocol\n if (stakeDurationInfo.duration >= stakeDurationForPerks && amount >= stakeAmountForPerks) {\n highTierAccounts[_msgSender()] = true;\n }\n\n userStakingInfo[_msgSender()].push(stakingInfo);\n\n uint256 stakeIndex = userStakingInfo[_msgSender()].length - 1;\n uint256 weightedStake = (amount * stakeDurationInfo.multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake += weightedStake;\n totalStaked += amount;\n\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit Staked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Withdraw staked tokens after stakeDuration has passed.\n * @dev Emits a `Unstaked` event upon successful withdrawal.\n * On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\n * @param amount The amount of tokens to withdraw.\n * @param stakeIndex The index of user staking pool\n */\n function unstake(\n uint256 amount,\n uint256 stakeIndex\n ) external nonReentrant notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n require(\n block.timestamp >= userStakingInfo[_msgSender()][stakeIndex].unStakeAt,\n \"Cannot unstake during staking period\"\n );\n require(\n amount <= userStakingInfo[_msgSender()][stakeIndex].stakedAmount,\n \"Insufficient unstake amount\"\n );\n\n _updateReward(_msgSender(), stakeIndex);\n\n uint256 multiplier = _getMultiplier(userStakingInfo[_msgSender()][stakeIndex].duration);\n\n uint256 currentWeightedStake = (amount * multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake -= currentWeightedStake;\n\n totalStaked -= amount;\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount -= amount;\n\n // check whether account is eligible for benefit from the protocol\n if (\n userStakingInfo[_msgSender()][stakeIndex].duration >= stakeDurationForPerks &&\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount < stakeAmountForPerks\n ) {\n highTierAccounts[_msgSender()] = false;\n }\n\n // remove staking info from array on full withdrawal\n if (userStakingInfo[_msgSender()][stakeIndex].stakedAmount == 0) {\n _claimReward(_msgSender(), stakeIndex);\n\n userStakingInfo[_msgSender()][stakeIndex] = userStakingInfo[_msgSender()][\n userStakingInfo[_msgSender()].length - 1\n ];\n userStakingInfo[_msgSender()].pop();\n }\n stakeRewardToken.safeTransfer(_msgSender(), amount);\n\n emit Unstaked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Claim pending rewards.\n * @dev Emits a `RewardPaid` event upon successful reward claim.\n * @param stakeIndex The index of user staking pool.\n */\n function getReward(uint256 stakeIndex) external nonReentrant notBlacklisted(_msgSender()) {\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n _updateReward(_msgSender(), stakeIndex);\n _claimReward(_msgSender(), stakeIndex);\n }\n\n // --------------------\n // ADMIN CONFIGURATION\n // --------------------\n\n /**\n * @notice Update Rewards Duration.\n * @dev Only callable by owner, and setting available only after rewards period.\n * @param duration New reward duration in seconds.\n */\n function setRewardsDuration(uint256 duration) external onlyOwner {\n require(finishAt < block.timestamp, \"reward duration is not finished\");\n rewardsDuration = duration;\n }\n\n /**\n * @notice Update stakeDurationForPerks\n * @dev Only callable by owner.\n * @param stakeDurationForPerks_ New stakeDurationForPerks.\n */\n function setStakeDurationForPerks(uint256 stakeDurationForPerks_) external onlyOwner {\n stakeDurationForPerks = stakeDurationForPerks_;\n }\n\n /**\n * @notice Update stakeAmountForPerks\n * @dev Only callable by owner.\n * @param stakeAmountForPerks_ New stakeDurationForPerks.\n */\n function setStakeAmountForPerks(uint256 stakeAmountForPerks_) external onlyOwner {\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n /**\n * @notice Push stakeDurationInfo\n * @dev Only callable by owner.\n */\n function pushStakeDurationInfo(StakeDurationInfo memory durationInfo) external onlyOwner {\n stakeDurationInfos.push(durationInfo);\n }\n\n /**\n * @notice Notify the contract about the amount of rewards to be distributed and update reward parameters.\n * @dev Only callable by owner.\n * @param amount The amount of reward to be distributed.\n */\n function notifyRewardAmount(uint256 amount) external onlyOwner {\n require(rewardsDuration > 0, \"rewards duration is not set\");\n require(amount > 0, \"amount = 0\");\n\n _updateReward(address(0), 0);\n\n if (block.timestamp >= finishAt) {\n rewardRatePerSec = amount / rewardsDuration;\n } else {\n uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatePerSec;\n rewardRatePerSec = (amount + remainingRewards) / rewardsDuration;\n }\n\n require(rewardRatePerSec > 0, \"reward rate = 0\");\n require(\n rewardRatePerSec <=\n (stakeRewardToken.balanceOf(address(this)) + amount - totalStaked) /\n rewardsDuration,\n \"reward amount > balance\"\n );\n\n finishAt = block.timestamp + rewardsDuration;\n lastUpdateTime = block.timestamp;\n\n totalRewards += amount;\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit NotifiedRewardAmount(amount, rewardRatePerSec);\n }\n\n // --------------------\n // VIEW FUNCTIONS\n // --------------------\n\n /**\n * @notice Get the last time when rewards were applicable for the specified reward token.\n * @return Timestamp of the most recent rewards calculation.\n */\n function lastTimeRewardApplicable() public view returns (uint256) {\n return _min(finishAt, block.timestamp);\n }\n\n /**\n * @notice Calculate the reward per token for a given reward token.\n * @return Current reward per token.\n */\n function rewardPerToken() public view returns (uint256) {\n if (totalStaked == 0) {\n return rewardPerTokenStored;\n }\n\n return\n rewardPerTokenStored +\n ((rewardRatePerSec * (lastTimeRewardApplicable() - lastUpdateTime) * 1e18) /\n totalWeightedStake);\n }\n\n /**\n * @notice Calculate the user's stake pool earnings\n * @param account Address of the user.\n * @param stakeIndex Index of the stakePool\n * @return Return earned amounts\n */\n function earned(address account, uint256 stakeIndex) public view returns (uint256) {\n StakingInfo memory userInfo = userStakingInfo[account][stakeIndex];\n uint256 multiplier = _getMultiplier(userInfo.duration);\n uint256 weightedAmount = (userInfo.stakedAmount * multiplier) / MULTIPLIER_BASIS;\n uint256 rewardsSinceLastUpdate = ((weightedAmount *\n (rewardPerToken() - userInfo.rewardPerTokenPaid)) / 1e18);\n return rewardsSinceLastUpdate + userInfo.rewards;\n }\n\n /**\n * @notice Get the earned rewards array for a user.\n * @param account Address of the user.\n * @return Return earned rewards array for a user.\n */\n function getEarnedUser(address account) public view returns (uint256[] memory) {\n uint256 numberOfPools = userStakingInfo[account].length;\n uint256[] memory earnedArray = new uint256[](numberOfPools);\n for (uint256 index; index < numberOfPools; index++) {\n earnedArray[index] = earned(account, index);\n }\n return earnedArray;\n }\n\n /**\n * @dev tierOf() function that always return that the given account is not\n * elligible to any LDY staking tier, except if the account is in the\n * highTierAccounts mapping.\n * @param account The account to check the tier of.\n */\n function tierOf(address account) public view returns (uint256 tier) {\n if (highTierAccounts[account]) return 3;\n return 0;\n }\n\n /**\n * @notice Get User Stake Data.\n * @param account The address of user.\n * @return StakingInfo array.\n */\n function getUserStakes(address account) external view returns (StakingInfo[] memory) {\n return userStakingInfo[account];\n }\n\n /**\n * @notice Get StakeDurationInfo.\n * @param index Index of StakeDurationInfos.\n * @return StakeDurationInfo.\n */\n function getStakeDurationInfo(uint256 index) external view returns (StakeDurationInfo memory) {\n require(stakeDurationInfos.length - 1 >= index, \"wrong index\");\n return stakeDurationInfos[index];\n }\n\n /**\n * @notice Send rewards to user.\n * @dev This is private function, called by getReward function.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _claimReward(address account, uint256 stakeIndex) private {\n uint256 reward = userStakingInfo[account][stakeIndex].rewards;\n\n if (reward > 0) {\n userStakingInfo[account][stakeIndex].rewards = 0;\n totalRewards -= reward;\n stakeRewardToken.safeTransfer(account, reward);\n emit RewardPaid(account, stakeIndex, reward);\n }\n }\n\n /**\n * @notice Calculate and update user rewards per stakeIndex.\n * @dev this is private function, called by stake, unstake, getRewards, and notifyRewardAmount functions.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _updateReward(address account, uint256 stakeIndex) private {\n rewardPerTokenStored = rewardPerToken();\n lastUpdateTime = lastTimeRewardApplicable();\n\n if (account != address(0)) {\n userStakingInfo[account][stakeIndex].rewards = earned(account, stakeIndex);\n userStakingInfo[account][stakeIndex].rewardPerTokenPaid = rewardPerTokenStored;\n }\n }\n\n /**\n * @notice Get multiplier from stakeDurationInfo based on duration\n * @param duration Stake Duration\n */\n function _getMultiplier(uint256 duration) private view returns (uint256) {\n uint256 stakeDurationInfosLength = stakeDurationInfos.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[i];\n if (duration == stakeDurationInfo.duration) {\n return stakeDurationInfo.multiplier;\n }\n }\n return 0;\n }\n\n /**\n * @notice Take minimum value between x and y.\n */\n function _min(uint256 x, uint256 y) private pure returns (uint256) {\n return x <= y ? x : y;\n }\n}\n" + }, + "contracts/src/libs/APRHistory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n/**\n * @title APRHistory\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This library offers utilities to efficiently maintain the history of an\n * on-chain APR (Annual Percentage Rate) state. Each entry in this history is called\n * a \"checkpoint\".\n *\n * @dev Intuition:\n * Each checkpoint in an APR history consists of two data:\n * - the creation timestamp\n * - the APR at that time\n *\n * Given that reading and writing to storage slots are among the most costly operations\n * in Solidity, this library provides a way to store those data in a way that minimizes\n * the number of used storage slots.\n *\n * Instead of storing each checkpoint in a separate storage slot, this library\n * facilitates the packing of up to 4 checkpoints in a single storage slot.\n *\n * @dev Definitions:\n * - Checkpoint: A record of an APR change\n * - Pack: A collection of 4 checkpoints stored in a single storage slot\n * - History: A dynamic array of packs\n * - Reference: A storage pointer to a checkpoint in the APR history\n * - CheckpointData: An in-memory representation of a checkpoint data\n *\n * @dev Value limitation:\n * This library can accommodate APRs only up to 65.536%. This is however sufficient for\n * APR in LToken contract, which is expected to remain below 10%.\n *\n * @dev For further details, see \"APRHistory\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary APRHistory {\n /**\n * @notice Represents data of a checkpoint extracted from the on-chain history.\n * For on-chain representation see \"Pack\" struct.\n * @param aprUD7x3 APR in UD7x3 format (e.g., 12345 = 12.345%).\n * @param timestamp Timestamp of the checkpoint's creation.\n */\n struct CheckpointData {\n uint16 aprUD7x3; // Allows up to 65.536%\n uint40 timestamp; // Supports dates up to 20/02/36812\n }\n\n /**\n * @notice Represents how APR checkpoints are stored on chain. Each pack can contain\n * the data 4 checkpoints. Packs are then stored in a dynamic array (the history).\n * @param aprsUD7x3 Array of checkpoints' APRs.\n * @param timestamps Array of checkpoints' timestamps.\n * @param cursor Index of the next checkpoint to be written.\n */\n struct Pack {\n uint16[4] aprsUD7x3;\n uint40[4] timestamps;\n uint32 cursor;\n }\n\n /**\n * @notice Represents a storage pointer to a specific checkpoint in the history.\n * @param packIndex Index of the pack the checkpoint belongs to.\n * @param cursorIndex Index of the checkpoint in this pack (between 0 and 3).\n */\n struct Reference {\n uint256 packIndex;\n uint32 cursorIndex;\n }\n\n /**\n * @notice Compares two checkpoints references.\n * @param ref1 The first reference to compare.\n * @param ref2 The second reference to compare.\n * @return Whether the two references points to the same checkpoint.\n */\n function eq(Reference memory ref1, Reference memory ref2) external pure returns (bool) {\n return ref1.packIndex == ref2.packIndex && ref1.cursorIndex == ref2.cursorIndex;\n }\n\n /**\n * @notice Returns the reference of the checkpoint that should come right after the\n * referenced checkpoint in the APR history.\n * @param ref The reference to be incremented.\n * @return The incremented reference.\n */\n function incrementReference(Reference memory ref) public pure returns (Reference memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L1\");\n\n // If the given ref is the last slot in its pack, return ref of next pack's first slot\n if (ref.cursorIndex == 3) return Reference(ref.packIndex + 1, 0);\n //\n // Else, return ref of next slot in current pack\n else return Reference(ref.packIndex, ref.cursorIndex + 1);\n }\n\n /**\n * @notice Extracts checkpoint data from a given reference and in APR history.\n * @param self The APR history to extract the checkpoint from.\n * @param ref The reference of the checkpoint data to extract.\n * @return The extracted checkpoint's data.\n */\n function getDataFromReference(\n Pack[] storage self,\n Reference memory ref\n ) public view returns (CheckpointData memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L2\");\n\n // Ensure pack index of the given ref exists in history\n require(ref.packIndex < self.length, \"L3\");\n\n // Retrieve pack data from history\n Pack memory pack = self[ref.packIndex];\n\n // Ensure cursor index of the given ref has been written\n require(ref.cursorIndex < pack.cursor, \"L4\");\n\n // Build and return the checkpoint data\n return\n CheckpointData({\n aprUD7x3: pack.aprsUD7x3[ref.cursorIndex],\n timestamp: pack.timestamps[ref.cursorIndex]\n });\n }\n\n /**\n * @notice Retrieves the reference to the most recently added checkpoint in the APR history.\n * @param self The history to extract the reference from.\n * @return The reference of the latest checkpoint.\n */\n function getLatestReference(Pack[] storage self) public view returns (Reference memory) {\n // Ensure the given history is not empty\n require(self.length != 0, \"L5\");\n\n // Retrieve latest pack's index and cursor\n uint256 packIndex = self.length - 1;\n uint32 packCursor = self[packIndex].cursor;\n\n // If this is the first pack ever, ensure it is not empty\n if (packIndex == 0) require(packCursor != 0, \"L6\");\n\n // If the pack is empty, return ref of previous pack's latest slot\n if (packCursor == 0) return Reference(packIndex - 1, 3);\n //\n // Else, return ref of previous slot in current pack\n else return Reference(packIndex, packCursor - 1);\n }\n\n /**\n * @notice Appends a new empty pack to the end of the given APR history array.\n * @param self The APR history to append an empty to.\n */\n function newBlankPack(Pack[] storage self) internal {\n // If history is not empty, ensure the latest pack is full\n require(self.length == 0 || getLatestReference(self).cursorIndex == 3, \"L7\");\n\n // Push a new blank pack to the history array\n self.push(\n Pack({\n aprsUD7x3: [uint16(0), uint16(0), uint16(0), uint16(0)],\n timestamps: [uint40(0), uint40(0), uint40(0), uint40(0)],\n cursor: 0\n })\n );\n }\n\n /**\n * @notice Write a new APR checkpoint at the end of the given history array.\n * @param self The array of packs to write the new checkpoint to.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(Pack[] storage self, uint16 aprUD7x3) external {\n // Determine the reference where the new checkpoint should be written\n Reference memory newRef = self.length == 0\n ? Reference(0, 0)\n : incrementReference(getLatestReference(self));\n\n // If pack to be written doesn't exist yet, push a new blank pack in history\n if (newRef.packIndex >= self.length) newBlankPack(self);\n\n // Retrieve the pack where the new checkpoint will be stored\n Pack memory pack = self[newRef.packIndex];\n\n // Add new checkpoint's data to the pack\n pack.aprsUD7x3[newRef.cursorIndex] = aprUD7x3;\n pack.timestamps[newRef.cursorIndex] = uint40(block.timestamp);\n\n // Increment the pack's cursor\n pack.cursor++;\n\n // Write the updated pack in storage\n self[newRef.packIndex] = pack;\n }\n\n /**\n * @notice Retrieves the APR of the latest checkpoint written in the APR history.\n * @param self The history array to read APR from.\n * @return The latest checkpoint's APR.\n */\n function getAPR(Pack[] storage self) public view returns (uint16) {\n // Retrieve the latest checkpoint data\n Reference memory ref = getLatestReference(self);\n CheckpointData memory data = getDataFromReference(self, ref);\n\n // Return the latest checkpoint's APR\n return data.aprUD7x3;\n }\n}\n" + }, + "contracts/src/libs/SUD.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title SUD\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice SUD serves as an intermediary number format for calculations within this\n * codebase. It ensures consistency and reduces precision losses. This library\n * facilitates conversions between various number formats and the SUD format.\n *\n * @dev Intuition:\n * This codebase employs the UD (unsigned decimal fixed-point numbers) format to\n * represent both percentage rates and tokens amounts.\n *\n * Rates are expressed in UD7x3 format, whereas the format for tokens amounts depends on\n * the decimals() value of the involved tokens.\n *\n * Three challenges arise from this:\n * 1) To compute values together, it's essential that they are in the same format\n * 2) Calculations involving consecutive divisions on UD numbers lead to accumulated\n * precision loss (because division shrinks). A common approach is to scale up and\n * down values by a few decimals before and after performing calculations.\n * 3) Given that rates use the UD7x3 format, if we decided to scale them to and from\n * the number of decimals of the involved token, 1 to 3 of the rates' decimals would\n * be shrunk in case token's decimals number is in [0, 2].\n *\n * To address these challenges, this library provides the SUD format, which acts as a\n * consistent and scaled intermediate format to perform calculations.\n *\n * SUD is an acronym for either \"Scaled UD\" or \"Safe UD\".\n *\n * @dev Definitions:\n * - Integer: A number without fractional part, e.g., block.timestamp\n * - UD: A decimal unsigned fixed-point number. The \"UD\" notation is inspired from\n * libraries like [prb-math](https://github.com/PaulRBerg/prb-math/)\n * - Amount: A token amount. A UD with an unknown repartition of digits between integral\n * and fractional parts (as token amounts have variable decimal numbers)\n * - Rate: A percentage rate. An UD with 7 integral digits and 3 fractional ones (= UD7x3)\n * - SUD: An intermediate format to perform calculations involving Rates and Amounts. A UD\n * with 3 more decimals than the involved UD with the highest decimals number. As\n * rates are represented by UD7x3, a SUD number has at least 6 decimals (3+3) and\n * so ranges from UD71x6 to UD0x77 formats.\n *\n * @dev A conversion library:\n * This library provides utilities to perform the following conversions:\n * - Amount <--> SUD\n * - Rate (UD7x3) <--> SUD\n * - Integer <--> SUD\n *\n * @dev Why scaling by 3 decimals?\n * - It provides an adequate degree of precision for this codebase,\n * - It enables the conversion of a UD7x3 rate to SUD format by merely scaling it up by\n * the involved token's decimal number, so is gas efficient.\n *\n * @dev Why internal functions?\n * The functions of this library are not set to external because incorporating them\n * directly into contracts is more gas-efficient. Given their minimal size and frequent\n * usage in the InvestUpgradeable, LDYStaking, and LToken contracts, any bytecode savings\n * from making them external are negated by the additional bytecode required for external\n * calls to this library. This can be observed by comparing the output of `bun cc:size`\n * when those functions's visibility is set to external or internal.\n *\n * @dev Precision warning:\n * While this library mitigates precision loss during calculations on UD numbers, it's\n * important to note that tokens with lower decimal counts and supply inherently suffer\n * more from precision loss. Conversely, tokens with higher decimal counts and supply\n * will experience less precision loss.\n *\n * @dev For further details, see \"SUD\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary SUD {\n /**\n * @notice Retrieves decimals number of the given ERC20 contract address.\n * @param tokenAddress The address to retrieve decimals number from.\n * @return decimals The decimals number of the given ERC20 contract address.\n */\n function decimalsOf(address tokenAddress) internal view returns (uint256 decimals) {\n return IERC20MetadataUpgradeable(tokenAddress).decimals();\n }\n\n /**\n * @notice Convert a given token amount into SUD format.\n * @param nAmount The token amount to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The amount in SUD format\n */\n function fromAmount(uint256 nAmount, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nAmount * 10 ** (6 - decimals);\n\n // Else return a number with decimals+3 fractional digits\n return nAmount * 10 ** 3;\n }\n\n /**\n * @notice Convert a given SUD number into token amount format.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nAmount The number in amount format\n */\n function toAmount(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nAmount) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** (6 - decimals);\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** 3;\n }\n\n /**\n * @notice Converts a given UD7x3 rate into SUD format.\n * @param nUD7x3 The UD7x3 rate to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The rate in SUD format.\n */\n function fromRate(uint256 nUD7x3, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nUD7x3 * 10 ** 3;\n\n // Else, return a number with decimals+3 fractional digits\n return nUD7x3 * 10 ** decimals;\n }\n\n /**\n * @notice Converts a given SUD number into a UD7x3 rate.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nUD7x3 The number in UD7x3 rate format.\n */\n function toRate(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nUD7x3) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 3;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** decimals;\n }\n\n /**\n * @notice Converts a given integer into SUD format.\n * @param n The integer to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The integer in SUD format.\n */\n function fromInt(uint256 n, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return n * 10 ** 6;\n\n // Else, return a number with decimals+3 fractional digits\n return n * 10 ** (decimals + 3);\n }\n\n /**\n * @notice Converts a given SUD number as an integer (all decimals shrinked).\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return n The SUD number as an integer.\n */\n function toInt(uint256 nSUD, uint256 decimals) internal pure returns (uint256 n) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 6;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** (decimals + 3);\n }\n}\n" + }, + "contracts/src/LToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ERC20WrapperUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\";\nimport \"./abstracts/base/ERC20BaseUpgradeable.sol\";\nimport {InvestUpgradeable} from \"./abstracts/InvestUpgradeable.sol\";\nimport {LDYStaking} from \"./LDYStaking.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {SUD} from \"./libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {ITransfersListener} from \"./interfaces/ITransfersListener.sol\";\n\n/**\n * @title LToken\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e.,\n * investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin.\n * As soon as a wallet holds some L-Tokens, it starts receiving rewards in\n * the form of additional L-Tokens, which are auto-compounded over time.\n *\n * @dev Definitions:\n * - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio).\n * - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees).\n * - Instant: Processed immediately.\n * - Request: Queued for later processing.\n * - Big Request: A requested withdrawal exceeding half of the retention rate.\n * - (Withdrawal) queue: A list of all requested withdrawals sorted by priority.\n * - Request ID: The index of a withdrawal request in the queue array.\n * - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain.\n * - Fees Rate: Percentage of fees applied to successful withdrawals.\n * - Usable underlyings: Amount of underlying tokens that have been deposited through\n * expected ways and are so considered safe to use by the contract.\n * - Transfers listeners: External contracts listening on L-Tokens transfers.\n * - Fund wallet: Wallet managed by the Ledgity's financial team.\n * - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request\n * processing.\n *\n * Note that words between parenthesis are sometimes omitted for brevity.\n *\n * @dev Deployment notice:\n * This contract can safely receive funds immediately after initialization. (i.e., there\n * is no way for funds to be sent to non-owned addresses). It is, however, recommended to\n * replace ASAP owner and fund wallets with multi-sig wallets.\n *\n * @dev For further details, see \"LToken\" section of whitepaper.\n * @custom:oz-upgrades-unsafe-allow external-library-linking\n * @custom:security-contact security@ledgity.com\n */\ncontract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @dev Represents type of actions triggering ActivityEvent events.\n enum Action {\n Deposit,\n Withdraw\n }\n\n /// @dev Represents different status of actions triggering ActivityEvent events.\n enum Status {\n Queued,\n Cancelled,\n Success,\n Moved\n }\n\n /**\n * @notice Represents a withdrawal request in the queue.\n * @dev A request fits in a single storage slot (32 bytes).\n * @param account The account that initiated the request.\n * @param amount The amount of underlying tokens requested.\n */\n struct WithdrawalRequest {\n address account; // 20 bytes\n uint96 amount; // 12 bytes\n }\n\n /// @notice Upper limit of retention rate.\n uint32 private constant MAX_RETENTION_RATE_UD7x3 = 10 * 10 ** 3; // 10%\n\n /// @notice Upper limit of fees rate.\n uint32 private constant MAX_FEES_RATE_UD7x3 = 20 * 10 ** 3; // 20%\n\n /// @notice Used in activity events to represent the absence of request ID.\n int256 private constant NO_ID = -1;\n\n /// @notice Holds a reference to the LDYStaking contract.\n LDYStaking public ldyStaking;\n\n /// @notice Holds address of withdrawer wallet (managed by withdrawal server).\n address payable public withdrawer;\n\n /// @notice Holds address of fund wallet (managed by Ledgity financial team).\n address public fund;\n\n /// @notice Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\n uint32 public feesRateUD7x3;\n\n /// @notice Holds the retention rate in UD7x3 format.\n uint32 public retentionRateUD7x3;\n\n /// @notice Holds the amount of withdrawal fees not yet claimed by contract's owner.\n uint256 public unclaimedFees;\n\n /// @notice Holds the amount of L-Tokens currently in the withdrawal queue.\n uint256 public totalQueued;\n\n /**\n * @notice Holds the amount of underlying tokens considered as usable by the contract.\n * @dev Are usable, only underlying tokens deposit through deposit() or fund() functions.\n */\n uint256 public usableUnderlyings;\n\n /// @notice Holds an ordered list of active withdrawal requests.\n WithdrawalRequest[] public withdrawalQueue;\n\n /// @notice Holds the index of the next withdrawal request to process in the queue.\n uint256 public withdrawalQueueCursor;\n\n /**\n * @notice Holds a list of all currently frozen withdrawal requests.\n * @dev If a request emitter as been blacklisted, its request is moved here to prevent\n * it from blocking the queue.\n */\n WithdrawalRequest[] public frozenRequests;\n\n /**\n * @notice Holds a list of contracts' references that are listening to L-Tokens transfers.\n * @dev onLTokenTransfer() functions of those contracts will be called on each transfer.\n */\n ITransfersListener[] public transfersListeners;\n\n /**\n * @notice Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet.\n */\n uint256 public withdrwalFeeInEth;\n\n /**\n * @notice Emitted to inform listeners about a change in the contract's TVL.\n * @dev TVL = realTotalSupply()\n * @param newTVL The new TVL of the contract.\n */\n event TVLChangeEvent(uint256 newTVL);\n\n /**\n * @notice Emitted to inform listerners about an activity related to deposits and withdrawals.\n * @param id ID of the involved withdrawal request or NO_ID (-1) if not applicable.\n * @param account The account involved in the activity.\n * @param action The type of activity.\n * @param amount The amount of underlying tokens involved in the activity.\n * @param newStatus The new status of the activity.\n * @param newId The new ID of the request if it has been moved in the queue.\n */\n event ActivityEvent(\n int256 indexed id,\n address indexed account,\n Action indexed action,\n uint256 amount,\n uint256 amountAfterFees,\n Status newStatus,\n int256 newId\n );\n\n /**\n * @notice Emitted to inform listeners that some rewards have been minted.\n * @param account The account that received the rewards.\n * @param balanceBefore The balance of the account before the minting.\n * @param rewards The amount of minted rewards.\n */\n event MintedRewardsEvent(address indexed account, uint256 balanceBefore, uint256 rewards);\n\n /// @notice Reverts if the function caller is not the withdrawer wallet.\n modifier onlyWithdrawer() {\n require(_msgSender() == withdrawer, \"L39\");\n _;\n }\n\n /// @notice Reverts if the function caller is not the fund wallet.\n modifier onlyFund() {\n require(_msgSender() == fund, \"L40\");\n _;\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param underlyingToken The address of the underlying stablecoin ERC20 token.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address ldyStaking_,\n address underlyingToken\n ) public initializer {\n // Initialize ERC20 base.\n string memory underlyingSymbol = IERC20MetadataUpgradeable(underlyingToken).symbol();\n __ERC20Base_init(\n globalOwner_,\n globalPause_,\n globalBlacklist_,\n string(abi.encodePacked(\"Ledgity \", underlyingSymbol)),\n string(abi.encodePacked(\"L\", underlyingSymbol))\n );\n\n // IMPORTANT: Below calls must not be restricted to owner at any point.\n // This is because the GlobalOwner contract may not be a fresh one, and so\n // the contract deployer may not be the owner anymore after ERC20Base init.\n\n // Initialize other parents contracts.\n __ERC20Wrapper_init(IERC20Upgradeable(underlyingToken));\n __Invest_init_unchained(address(this));\n\n // Set LDYStaking contract\n ldyStaking = LDYStaking(ldyStaking_);\n\n // Set initial withdrawal fees rate to 0.3%\n feesRateUD7x3 = 300;\n\n // Set initial retention rate to 10%\n retentionRateUD7x3 = 10_000;\n\n // Default withdrawer and fund wallet to contract owner address. This prevents\n // any loss of funds if a deposit/withdrawal is made before those are manually set.\n withdrawer = payable(owner());\n fund = payable(owner());\n\n // Set initial withdrwalFeeInEth\n withdrwalFeeInEth = 0.00075 * 1e18;\n }\n\n /**\n * @notice Required override of decimals() which is implemented by both\n * ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\n * @dev The ERC20WrapperUpgradeable version is preferred because it mirrors the\n * decimals amount of the underlying stablecoin token.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function decimals()\n public\n view\n override(ERC20Upgradeable, ERC20WrapperUpgradeable)\n returns (uint8)\n {\n return ERC20WrapperUpgradeable.decimals();\n }\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\n * @dev Both version are the same as ERC20BaseUpgradeable.paused() mirrors\n * GlobalPausableUpgradeable.paused(), so a random one is chosen.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, ERC20BaseUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @notice Updates the current withdrawal fee rate.\n * @param feesRateUD7x3_ The new withdrawal fee rate in UD7x3 format.\n */\n function setFeesRate(uint32 feesRateUD7x3_) public onlyOwner {\n require(feesRateUD7x3_ <= MAX_FEES_RATE_UD7x3, \"L88\");\n feesRateUD7x3 = feesRateUD7x3_;\n }\n\n /**\n * @notice Updates the current withdrawalFeeInETH.\n * @param withdrwalFeeInEth_ The new withdrawalFee in ETH.\n */\n function setWithdrwalFeeInEth(uint256 withdrwalFeeInEth_) public onlyOwner {\n require(withdrwalFeeInEth <= MAX_FEES_RATE_UD7x3, \"L88\");\n withdrwalFeeInEth = withdrwalFeeInEth_;\n }\n\n /**\n * @notice Updates the current underlying token retention rate.\n * @dev The retention rate is capped at 10%, which ensures that no more than 10% of\n * deposited assets will ever be exposed in this contract (reduces attack surface).\n * @param retentionRateUD7x3_ The new retention rate in UD7x3 format.\n */\n function setRetentionRate(uint32 retentionRateUD7x3_) public onlyOwner {\n require(retentionRateUD7x3_ <= MAX_RETENTION_RATE_UD7x3, \"L41\");\n retentionRateUD7x3 = retentionRateUD7x3_;\n }\n\n /**\n * @notice Updates the address of LDYStaking contract.\n * @param ldyStakingAddress The address of the new LDYStaking contract.\n */\n function setLDYStaking(address ldyStakingAddress) public onlyOwner {\n ldyStaking = LDYStaking(ldyStakingAddress);\n }\n\n /**\n * @notice Updates the address of the withdrawer wallet.\n * @param withdrawer_ The address of the new withdrawer wallet.\n */\n function setWithdrawer(address payable withdrawer_) public onlyOwner {\n // Ensure address is not the zero address (pre-processing fees would be lost else)\n require(withdrawer_ != address(0), \"L63\");\n\n // Set new withdrawer wallet's address\n withdrawer = withdrawer_;\n }\n\n /**\n * @notice Updates the address of the fund wallet.\n * @param fund_ The address of the new fund wallet.\n */\n function setFund(address payable fund_) public onlyOwner {\n // Ensure address is not the zero address (deposited tokens would be lost else)\n require(fund_ != address(0), \"L64\");\n\n // Set new fund wallet's address\n fund = fund_;\n }\n\n /**\n * @notice Adds a new contract to the L-Token transfers list.\n * @dev Each time a transfer occurs, the onLTokenTransfer() function of the\n * specified contract will be called.\n * @dev IMPORTANT SECURITY NOTE: This method is not intended to be used with\n * contracts that are not owned by the Ledgity team.\n * @param listenerContract The address of the new transfers listener contract.\n */\n function listenToTransfers(address listenerContract) public onlyOwner {\n transfersListeners.push(ITransfersListener(listenerContract));\n }\n\n /**\n * @notice Removes a contract from the L-Token transfers list.\n * @dev The onLTokenTransfer() function of the specified contract will not be called\n * anymore each time a L-Token transfer occurs.\n * @param listenerContract The address of the listener contract.\n */\n function unlistenToTransfers(address listenerContract) public onlyOwner {\n // Find index of listener contract in transferListeners array\n int256 index = -1;\n uint256 transfersListenersLength = transfersListeners.length;\n for (uint256 i = 0; i < transfersListenersLength; i++) {\n if (address(transfersListeners[i]) == listenerContract) {\n index = int256(i);\n break;\n }\n }\n\n // Revert if given contract wasn't listening to transfers\n require(index > -1, \"L42\");\n\n // Else, remove transfers listener contract from listeners array\n transfersListeners[uint256(index)] = transfersListeners[transfersListenersLength - 1];\n transfersListeners.pop();\n }\n\n /**\n * @notice Retrieves the amount of given account's not yet minted rewards.\n * @dev This is a public implementation of InvestUpgradeable_rewardsOf(). In the\n * context of LToken, this function returns the amount of rewards that have not been\n * distributed/minted yet to the specified account.\n * @dev This is particularly useful for off-chain services to display charts and\n * statistics, as seen in the Ledgity Yield's frontend.\n * @param account The account to check the unminted rewards of.\n * @return The amount of account's unminted rewards.\n */\n function unmintedRewardsOf(address account) public view returns (uint256) {\n return _rewardsOf(account, true);\n }\n\n /**\n * @notice Retrieves the \"real\" balance of an account, i.e., excluding its not yet\n * minted/distributed rewards.\n * @param account The account to check the real balance of.\n * @return The real balance of the account.\n */\n function realBalanceOf(address account) public view returns (uint256) {\n return super.balanceOf(account);\n }\n\n /**\n * @notice Retrieves the total balance of L-Tokens that belong to the account.\n * @dev This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have\n * not been yet minted to the specified account.\n * @param account The account to check the total balance of.\n * @return The total balance of the account.\n */\n function balanceOf(address account) public view override returns (uint256) {\n return realBalanceOf(account) + unmintedRewardsOf(account);\n }\n\n /**\n * @notice Returns the \"real\" amount of existing L-Tokens, i.e., excluding not yet\n * minted withdrawal fees and L-Tokens currently in the withdrawal queue.\n * @return The real total supply of L-Tokens.\n */\n function realTotalSupply() public view returns (uint256) {\n return super.totalSupply();\n }\n\n /**\n * @notice Retrives the total supply of L-Tokens, including not yet minted withdrawal\n * fees and L-Tokens currently in the withdrawal queue.\n * @return The total supply of L-Tokens.\n */\n function totalSupply() public view override returns (uint256) {\n return realTotalSupply() + totalQueued + unclaimedFees;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address.\n * @dev This override of RecoverableUpgradeable.recoverERC20() prevents the recovered\n * token from being the underlying token.\n * @inheritdoc RecoverableUpgradeable\n */\n function recoverERC20(address tokenAddress, uint256 amount) public override onlyOwner {\n // Ensure the token is not the underlying token\n require(tokenAddress != address(underlying()), \"L43\");\n\n // Proceed to recovery\n super.recoverERC20(tokenAddress, amount);\n }\n\n /**\n * @notice Recovers underlying tokens accidentally sent to the contract.\n * @dev To prevent owner from being able to drain the contract, this function only\n * allows recovering \"unusable\" underlying tokens, i.e., tokens that have not been\n * sent through fund() or deposit() functions.\n */\n function recoverUnderlying() external onlyOwner {\n // Compute the recoverable amount by taking the difference between the contract's\n // balance and the amount of usable underlying tokens\n uint256 recoverableAmount = underlying().balanceOf(address(this)) - usableUnderlyings;\n\n // Revert if there is nothing to recover\n require(recoverableAmount > 0, \"L44\");\n\n // Else, proceed to underlying tokens recovery\n super.recoverERC20(address(underlying()), recoverableAmount);\n }\n\n /**\n * @notice Retrieves the amount of underlying tokens invested by the given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract. In\n * LToken contract, the investment of an account is equal to its real balance.\n * @inheritdoc InvestUpgradeable\n */\n function _investmentOf(address account) internal view override returns (uint256) {\n return realBalanceOf(account);\n }\n\n /**\n * @notice Distributes a specified amount of rewards (in L-Tokens) to a given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract so\n * it can distribute rewards to accounts before each period reset.\n * @dev InvestUpgradeable contract already ensure that amount > 0.\n * @inheritdoc InvestUpgradeable\n */\n function _distributeRewards(address account, uint256 amount) internal override returns (bool) {\n // Inform listeners of the rewards minting\n emit MintedRewardsEvent(account, realBalanceOf(account), amount);\n\n // Mint L-Tokens rewards to account\n _mint(account, amount);\n\n // Return true indicating to InvestUpgradeable that the rewards have been distributed\n return true;\n }\n\n /**\n * @notice Override of ERC20._beforeTokenTransfer() to integrate with InvestUpgradeable.\n * @dev This overriden version ensure that _beforeInvestmentChange() hook is properly\n * called each time an account's balance is going to change.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already included in ERC20BaseUpgradeable._beforeTokenTransfer().\n * @inheritdoc ERC20BaseUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20Upgradeable, ERC20BaseUpgradeable) {\n ERC20BaseUpgradeable._beforeTokenTransfer(from, to, amount);\n\n // Invoke _beforeInvestmentChange() hook for non-zero accounts\n if (from != address(0)) _beforeInvestmentChange(from, true);\n if (to != address(0)) _beforeInvestmentChange(to, true);\n }\n\n /**\n * @notice Override of ERC20._afterTokenTransfer() to notify all transfers listeners.\n * @dev This overriden version will trigger onLTokenTransfer() functions of all\n * transfers listeners.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already checked in _beforeTokenTransfer().\n * @inheritdoc ERC20Upgradeable\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\n super._afterTokenTransfer(from, to, amount);\n\n // If some L-Token have been burned/minted, inform listeners of a TVL change\n if (from == address(0) || to == address(0)) emit TVLChangeEvent(totalSupply());\n\n // Trigger onLTokenTransfer() functions of all the transfers listeners\n for (uint256 i = 0; i < transfersListeners.length; i++) {\n transfersListeners[i].onLTokenTransfer(from, to, amount);\n }\n }\n\n /**\n * @notice Computes the maximum amount of underlying tokens that should be retained\n * by the contract (based on retention rate).\n * @return amount The expected amount of retained underlying tokens.\n */\n function getExpectedRetained() public view returns (uint256 amount) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert totalSupply and retentionRate to SUD\n uint256 totalSupplySUD = SUD.fromAmount(totalSupply(), d);\n uint256 retentionRateSUD = SUD.fromRate(retentionRateUD7x3, d);\n\n // Compute and return expected retained amount\n uint256 expectedRetainedSUD = (totalSupplySUD * retentionRateSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(expectedRetainedSUD, d);\n }\n\n /// @notice Transfers underlying tokens exceeding the retention rate to the fund wallet.\n function _transferExceedingToFund() internal {\n // Retrieve the expected amount retained\n uint256 expectedRetained = getExpectedRetained();\n\n // If usable underlyings are less than or equal to expected retained, return\n if (usableUnderlyings <= expectedRetained) return;\n\n // Else, exceeding amount is equal to difference between those values\n uint256 exceedingAmount = usableUnderlyings - expectedRetained;\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= exceedingAmount;\n\n // Transfer the exceeding amount to the fund wallet\n underlying().safeTransfer(fund, exceedingAmount);\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.withdrawTo() that reverts.\n * Use instantWithdrawal() or requestWithdrawal() functions instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function withdrawTo(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L45\");\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.depositFor() that reverts.\n * Use deposit() function instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function depositFor(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L46\");\n }\n\n /**\n * @notice Allows exchanging some underlying tokens for the same amount of L-Tokens.\n * @param amount The amount of underlying tokens to deposit.\n */\n function deposit(uint256 amount) public whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough underlying tokens to deposit\n require(underlying().balanceOf(_msgSender()) >= amount, \"L47\");\n\n // Update usable underlyings balance accordingly\n usableUnderlyings += amount;\n\n // Inform listeners of the deposit activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Deposit,\n amount,\n amount,\n Status.Success,\n NO_ID\n );\n\n // Receive underlying tokens and mint L-Tokens to the account in a 1:1 ratio\n super.depositFor(_msgSender(), amount);\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Computes fees and net withdrawn amount for a given account withdrawing a\n * given amount.\n * @param account The account initiating the withdrawal.\n * @param amount The amount of the withdrawal.\n */\n function getWithdrawnAmountAndFees(\n address account,\n uint256 amount\n ) public view returns (uint256 withdrawnAmount, uint256 fees) {\n // If the account is eligible to staking tier 2, no fees are applied\n if (ldyStaking.tierOf(account) >= 2) return (amount, 0);\n\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert amount and fees rate to SUD\n uint256 amountSUD = SUD.fromAmount(amount, d);\n uint256 feesRateSUD = SUD.fromRate(feesRateUD7x3, d);\n\n // Compute fees and withdrawn amount (initial amount minus fees)\n uint256 feesSUD = (amountSUD * feesRateSUD) / SUD.fromInt(100, d);\n fees = SUD.toAmount(feesSUD, d);\n withdrawnAmount = amount - fees;\n }\n\n /**\n * @notice Allows instaneously exchanging a given amount of L-Tokens for the same\n * amount of underlying tokens. It will fail if the contract currently doesn't hold\n * enough underlying tokens to cover the withdrawal.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestWithdrawal() function otherwise.\n * @param amount The amount L-Tokens to withdraw.\n */\n function instantWithdrawal(uint256 amount) external whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L48\");\n\n // Can the contract cover this withdrawal plus all already queued requests?\n bool cond1 = totalQueued + amount <= usableUnderlyings;\n\n // Is caller eligible to staking tier 2 and the contract can cover this withdrawal?\n bool cond2 = ldyStaking.tierOf(_msgSender()) >= 2 && amount <= usableUnderlyings;\n\n // Revert if conditions are not met for the withdrawal to be processed instantaneously\n if (!(cond1 || cond2)) revert(\"L49\");\n\n // Else, retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(_msgSender(), amount);\n\n // Increase unclaimed fees amount accordingly\n unclaimedFees += fees;\n\n // Decrease usable underlyings balance accordingly\n usableUnderlyings -= withdrawnAmount;\n\n // Inform listeners of this instant withdrawal activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Withdraw,\n amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Burn withdrawal fees from the account\n _burn(_msgSender(), fees);\n\n // Burn account's withdrawn L-Tokens and transfer to it underlying tokens in a 1:1 ratio\n super.withdrawTo(_msgSender(), withdrawnAmount);\n }\n\n /**\n * @notice Allows requesting the exchange of a given amount of L-Tokens for the same\n * amount of underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n * @param amount The amount L-Tokens to withdraw.\n */\n function requestWithdrawal(\n uint256 amount\n ) public payable whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L53\");\n\n // Ensure the requested amount doesn't overflow uint96\n require(amount <= type(uint96).max, \"L54\");\n\n // Ensure the sender attached the pre-paid processing gas fees\n require(msg.value == withdrwalFeeInEth, \"L55\");\n\n // Create withdrawal request data\n WithdrawalRequest memory request = WithdrawalRequest({\n account: _msgSender(),\n amount: uint96(amount)\n });\n\n // Will hold the request ID\n uint256 requestId;\n\n // Append request to the withdrawal queue:\n // - At the beginning, if account is eligible to staking tier 2 and cursor is not 0\n if (ldyStaking.tierOf(_msgSender()) >= 2 && withdrawalQueueCursor > 0) {\n withdrawalQueueCursor--;\n requestId = withdrawalQueueCursor;\n withdrawalQueue[requestId] = request;\n }\n // - At the end else\n else {\n withdrawalQueue.push(request);\n requestId = withdrawalQueue.length - 1;\n }\n\n // Increase total amount queued accordingly\n totalQueued += amount;\n\n // Inform listeners of this new queued withdrawal activity event\n emit ActivityEvent(\n int256(requestId),\n _msgSender(),\n Action.Withdraw,\n amount,\n amount,\n Status.Queued,\n NO_ID\n );\n\n // Burn withdrawal L-Tokens amount from account's balance\n _burn(_msgSender(), amount);\n\n // Forward pre-paid processing gas fees to the withdrawer wallet\n (bool sent, ) = withdrawer.call{value: msg.value}(\"\");\n require(sent, \"L56\");\n }\n\n /**\n * @notice Processes queued withdrawal requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n * @dev For further details, see \"LToken > Withdrawals\" section of whitepaper.\n */\n function processQueuedRequests() external onlyWithdrawer whenNotPaused {\n // Accumulators variables, will be written on-chain after the loop\n uint256 cumulatedFees = 0;\n uint256 cumulatedWithdrawnAmount = 0;\n uint256 nextRequestId = withdrawalQueueCursor;\n\n // Cache queue length to avoid multiple SLOADs and avoid infinite loop as big\n // requests are increasing the queue length when moved at the end of the queue.\n uint256 queueLength = withdrawalQueue.length;\n\n // Iterate over requests to be processed\n while (nextRequestId < queueLength) {\n // Stop processing requests if there is not enough gas left to continue the\n // loop and properly end the function call. This prevents an attacker from\n // blocking the withdrawal processing by creating a ton of tiny requests so\n // this function call cannot fit anymore in block gas limit.\n if (gasleft() < 45000) break;\n\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[nextRequestId];\n\n // Skip empty request (processed big requests or cancelled requests)\n if (request.account == address(0)) {}\n //\n // If account has been blacklisted since request emission\n else if (isBlacklisted(request.account)) {\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request in the frozen requests list\n frozenRequests.push(request);\n }\n //\n // Or if request is a big request, move it at the end of the queue for now.\n // This request will be processed manually later using processBigQueuedRequest()\n else if (request.amount > getExpectedRetained() / 2) {\n // Inform listeners of this queued request being moved at the end of the queue\n emit ActivityEvent(\n int256(nextRequestId),\n _msgSender(),\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Moved,\n int256(withdrawalQueue.length)\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request at the end of the queue\n withdrawalQueue.push(request);\n }\n //\n // Else, continue request processing\n else {\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Break if the contract doesn't hold enough funds to cover the request\n if (withdrawnAmount > usableUnderlyings - cumulatedWithdrawnAmount) break;\n\n // Accumulate fees and withdrawn amount\n cumulatedFees += fees;\n cumulatedWithdrawnAmount += withdrawnAmount;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(nextRequestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Transfer underlying tokens to account. Burning L-Tokens is not required\n // as equestWithdrawal() already did it.\n // Security note: Re-entrancy warning are disabled as the request has\n // just been deleted from the queue, it will so be skipped if trying to\n // process it again.\n // slither-disable-next-line reentrancy-no-eth\n underlying().safeTransfer(request.account, withdrawnAmount);\n }\n\n // Increment next request ID\n nextRequestId++;\n }\n\n // Increase unclaimed fees by the amount of cumulated fees\n unclaimedFees += cumulatedFees;\n\n // Decrease usable underlyings by the cumulated amount of withdrawn underlyings\n usableUnderlyings -= cumulatedWithdrawnAmount;\n\n // Decrease total amount queued by the cumulated amount requested\n totalQueued -= cumulatedWithdrawnAmount + cumulatedFees;\n\n // Update new queue cursor\n withdrawalQueueCursor = nextRequestId;\n\n // Retention rate cannot exceeds as the withdrawal decreases both usable\n // underlyings and expected retained amounts by the same number and as the\n // expected retained amount is a subset of usable underlyings amount.\n }\n\n /**\n * @notice Processes a given queued big withdrawal request (one that exceeds half of\n * the retention rate).\n * @dev In contrast to non-big requests processing, this function will uses to fund\n * wallet's balance to fill the request. This allows processing requests that are\n * greater than retention rate without having to exceed this rate on the contract.\n * @param requestId The ID of the big request to process.\n */\n function processBigQueuedRequest(uint256 requestId) external onlyFund whenNotPaused {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure the request is active\n require(request.account != address(0), \"L66\");\n\n // Ensure the request emitter has not been blacklisted since request emission\n require(!isBlacklisted(request.account), \"L50\");\n\n // Ensure this is indeed a big request\n require(request.amount > getExpectedRetained() / 2, \"L51\");\n\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Ensure withdrawn amount can be covered by contract + fund wallet balances\n uint256 fundBalance = underlying().balanceOf(fund);\n require(withdrawnAmount <= usableUnderlyings + fundBalance, \"L52\");\n\n // Increase amount of unclaimed fees accordingly\n unclaimedFees += fees;\n\n // Decrease total queued amount by request amount\n totalQueued -= request.amount;\n\n // Increment queue cursor if request was the next request to be processed\n if (requestId == withdrawalQueueCursor) withdrawalQueueCursor++;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[requestId];\n\n // If fund wallet's balance can cover request, rely on it only\n if (withdrawnAmount <= fundBalance) {\n underlying().safeTransferFrom(_msgSender(), request.account, withdrawnAmount);\n }\n // Else, cover request from both fund wallet and contract balances\n else {\n // Compute amount missing from fund wallet to cover request\n uint256 missingAmount = withdrawnAmount - fundBalance;\n\n // Decrease usable amount of underlying tokens accordingly\n usableUnderlyings -= missingAmount;\n\n // Transfer entire fund balance to request's emitter\n underlying().safeTransferFrom(_msgSender(), request.account, fundBalance);\n\n // Transfer missing amount from contract balance to request emitter\n underlying().safeTransfer(request.account, missingAmount);\n }\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Cancels a given withdrawal request. The request emitter receive back its\n * L-Tokens and no fees will be charged.\n * @param requestId The ID of the withdrawal request to cancel.\n */\n function cancelWithdrawalRequest(\n uint256 requestId\n ) public whenNotPaused notBlacklisted(_msgSender()) {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure request belongs to caller\n require(_msgSender() == request.account, \"L57\");\n\n // Decrease total amount queued accordingly\n totalQueued -= request.amount;\n\n // Delete the withdrawal request from queue\n delete withdrawalQueue[requestId];\n\n // Inform listeners of this cancelled withdrawal request activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Cancelled,\n NO_ID\n );\n\n // Mint back L-Tokens to account\n _mint(request.account, uint256(request.amount));\n }\n\n /**\n * @notice Used by the fund wallet to repatriate underlying tokens on the contract\n * whenever those are required to fulfill some withdrawal requests.\n * @dev The function will revert if repatriated amount makes the contract exceeding\n * the retention rate.\n * @param amount The amount of underlying tokens to repatriate.\n */\n function repatriate(uint256 amount) external onlyFund whenNotPaused {\n // Ensure the fund wallet has enough funds to repatriate\n require(amount <= underlying().balanceOf(fund), \"L58\");\n\n // Calculate new contract usable balance\n uint256 newBalance = usableUnderlyings + amount;\n\n // Ensure the new balance doesn't exceed the retention rate\n require(newBalance <= getExpectedRetained(), \"L59\");\n\n // Increase usable underlyings amount by repatriated amount\n usableUnderlyings += amount;\n\n // Transfer amount from fund wallet to contract\n underlying().safeTransferFrom(_msgSender(), address(this), amount);\n }\n\n /// @notice Used by owner to claim fees generated from successful withdrawals.\n function claimFees() external onlyOwner {\n // Ensure there are some fees to claim\n require(unclaimedFees > 0, \"L60\");\n\n // Ensure the contract holds enough underlying tokens to cover fees\n require(usableUnderlyings >= unclaimedFees, \"L61\");\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= unclaimedFees;\n\n // Store fees amount in memory and reset unclaimed fees amount\n uint256 fees = unclaimedFees;\n unclaimedFees = 0;\n\n // Transfer unclaimed fees to owner\n underlying().safeTransfer(owner(), fees);\n }\n}\n" + }, + "contracts/src/PreMining.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {LToken} from \"./LToken.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {Pausable} from \"@openzeppelin/contracts/security/Pausable.sol\";\n\n/**\n * @title PreMining\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n\n * @notice PreMining pool contract, allowing accounts to lock underlying tokens in a \n * pre-defined L-Token contract, over a given duration (in months), in exchange of \n * vested LDY rewards.\n * \n * @dev Intuition\n * \n * Lifecycle of a lockdrop pool is composed by 3 main phases:\n * 1) Deposit: During this phase, users can lock their underlying tokens.\n * 2) Claim: During this phase, users can claim their LDY rewards.\n * 3) Recovery: During this phase, owner can recover remaining ERC20 on the contract.\n * \n * Transitioning between two phases is manually triggered by contract's owner.\n * To ensure fair usage of this power and prevent potential misuse:\n * - the Recovery phase cannot start before 3 months after the end of rewards vesting,\n * - the Recovery phase cannot start before 3 months after the maximum lock end.\n * \n * Finally, note that this contract proxies main L-Token contract's functions:\n * - lock() --> deposit()\n * - instantUnlock() --> instantWithdrawal()\n * - requestUnlock() --> requestWithdrawal()\n * This design enables users to interact with the PreMining contract in a similar fashion\n * to the L-Token contract.\n * \n * @dev Definitions:\n * - Locker: An account that has locked underlying tokens in the pool.\n * \n * @custom:security-contact security@ledgity.com\n */\ncontract PreMining is Ownable2Step, Pausable {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Represents the lock information of an account.\n * @param amount Amount of underlying tokens locked.\n * @param duration Duration of the lock (in months).\n * @param hasUnlocked Whether the account has unlocked its locked tokens.\n * @param claimedRewards Amount of LDY rewards already claimed.\n * @param lockEndTimestamp Timestamp at which the account's lock ends.\n */\n struct AccountLock {\n uint240 amount;\n uint8 duration;\n bool hasUnlocked;\n uint216 claimedRewards;\n uint40 lockEndTimestamp;\n }\n\n /// @notice Holds the amount of LDY to be distributed to lockers.\n uint256 public immutable maxDistributedLDY;\n\n /// @notice Holds the maximum total amount of L-Tokens that can be locked.\n uint256 public immutable lockedHardCap;\n\n /// @notice Holds the minimum possible lock duration (in months).\n uint8 public immutable minLockDuration;\n\n /// @notice Holds the maximum possible lock duration (in months).\n uint8 public immutable maxLockDuration;\n\n /// @notice Holds the duration of LDY rewards vesting (in months).\n uint8 public immutable vestingDuration;\n\n /// @notice Holds a reference to the locked L-Token contract.\n LToken public immutable lToken;\n\n /// @notice Holds a reference to the L-Token underlying stablecoin.\n IERC20 public immutable underlyingToken;\n\n /// @notice Holds the max pool weight.\n uint256 public immutable maxWeight;\n\n /// @notice Holds a reference to the LDY token contract.\n IERC20 public ldyToken;\n\n /// @notice Holds lockers' participations informations.\n mapping(address => AccountLock) public accountsLocks;\n\n /// @notice Holds the total amount of locked underlying tokens.\n uint256 public totalLocked;\n\n /// @notice Holds whether the Deposit phase has ended.\n bool public hasDepositPhaseEnded;\n\n /// @notice Holds whether the Claim phase has started.\n bool public hasClaimPhaseStarted;\n\n /// @notice Holds whether the Recovery phase has started.\n bool public hasRecoveryPhaseStarted;\n\n /// @notice Holds the timestamp at which the Claim phase started.\n uint256 public claimPhaseStartTimestamp;\n\n /// @notice Holds an ordered queue of accounts that requested to unlock their tokens.\n address[] public unlockRequests;\n\n /// @notice Holds the index of the first request in the queue (a.k.a, next one to be processed).\n uint256 public unlockRequestsCursor;\n\n /// @notice Emitted to inform about a new lock/deposit.\n event Lock(address indexed account, uint256 amount, uint8 duration);\n\n /// @notice Top-level checks and code shared by both unlock functions.\n modifier safeUnlock() {\n // Ensure that the account's lock has ended\n require(accountsLocks[msg.sender].lockEndTimestamp <= block.timestamp, \"L68\");\n\n // Ensure the account hasn't already unlocked its tokens\n require(!accountsLocks[msg.sender].hasUnlocked, \"L69\");\n\n // Ensure the account has something to unlock\n require(accountsLocks[msg.sender].amount > 0, \"L70\");\n\n // Indicate that account has unlocked its tokens\n accountsLocks[msg.sender].hasUnlocked = true;\n _;\n }\n\n /**\n * @notice This constructor function etches the lockdrop terms in immutable states.\n * Ensuring that those terms cannot be modified after deployment.\n * @param lTokenAddress_ Address of the L-Token contract to use.\n * @param maxDistributedLDY_ Amount of LDY to be distributed to lockers.\n * @param lockedHardCap_ Maximum total amount of L-Tokens that can be locked.\n * @param minLockDuration_ Minimum possible lock duration (in months).\n * @param maxLockDuration_ Maximum possible lock duration (in months).\n * @param vestingDuration_ Duration of LDY rewards vesting (in months).\n */\n constructor(\n address lTokenAddress_,\n uint256 maxDistributedLDY_,\n uint256 lockedHardCap_,\n uint8 minLockDuration_,\n uint8 maxLockDuration_,\n uint8 vestingDuration_\n ) {\n // Ensure minLockDuration is at least 1 month\n require(minLockDuration_ >= 1, \"L72\");\n\n // Ensure minLockDuration is not greater than maxLockDuration\n require(minLockDuration_ <= maxLockDuration_, \"L73\");\n\n // Set immutable states\n lToken = LToken(lTokenAddress_);\n underlyingToken = IERC20(address(lToken.underlying()));\n lockedHardCap = lockedHardCap_;\n maxDistributedLDY = maxDistributedLDY_;\n minLockDuration = minLockDuration_;\n maxLockDuration = maxLockDuration_;\n vestingDuration = vestingDuration_;\n maxWeight = lockedHardCap * uint256(maxLockDuration);\n }\n\n /**\n * @notice Public implementation of Pausable's pausing and unpausing functions, but\n * restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Updates the LDY token contract address.\n * @dev As the first Ledgity Yield lockdrop campaigns will start before the LDY TGE,\n * this function allows the contract's owner to set the LDY token address once it\n * becomes available.\n * @param ldyTokenAddress Address of the LDY token contract.\n */\n function setLDYToken(address ldyTokenAddress) external onlyOwner {\n // Prevent owner from changing the LDY address after Claim phase has started\n require(!hasClaimPhaseStarted, \"L74\");\n\n // Set LDY token address\n ldyToken = IERC20(ldyTokenAddress);\n }\n\n /**\n * @notice Closes the Deposit phase. After calling this function, account won't be\n * able to lock additional underlying tokens anymore.\n */\n function endDepositPhase() external onlyOwner {\n hasDepositPhaseEnded = true;\n }\n\n /**\n * @notice Opens the Claim phase. After calling this function, lockers will be able\n * to start claiming their LDY rewards.\n */\n function startClaimPhase() external onlyOwner {\n // Ensure Claim phase has not already started\n require(!hasClaimPhaseStarted, \"L76\");\n\n // Ensure that LDY token address is available\n require(address(ldyToken) != address(0), \"L77\");\n\n // Set Claim phase as started and store the start timestamp\n hasClaimPhaseStarted = true;\n claimPhaseStartTimestamp = block.timestamp;\n }\n\n /**\n * @notice Opens the Recovery phase. After calling this function, the contract owner\n * will be able to recover remaining ERC20 tokens on the contract.\n * Note that this won't close the Claim phase and lockers will still be able to claim\n * their LDY rewards.\n */\n function startRecoveryPhase() external onlyOwner {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L79\");\n\n // Compute some durations in seconds\n uint256 threeMonthsInSecond = 3 * 30 days;\n uint256 vestingInSecond = uint256(vestingDuration) * 30 days;\n uint256 maxLockInSecond = uint256(maxLockDuration) * 30 days;\n\n // Compute timestamp of vesting end + 3 months\n uint256 afterVestingTimestamp = claimPhaseStartTimestamp +\n vestingInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the end of reward vesting\n // This prevents owner from recovering LDY before lockers can claim their rewards\n require(block.timestamp >= afterVestingTimestamp, \"L80\");\n\n // Compute end of maximum lock + 3 months\n // Note that claimPhaseStartTimestamp is used for simplicity even if it can exist a time\n // span between Deposit and Claim phases.\n uint256 afterMaxLockTimestamp = claimPhaseStartTimestamp +\n maxLockInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the maximum lock end\n // This prevents owner from recovering underlying tokens before lockers can unlock those\n require(block.timestamp >= afterMaxLockTimestamp, \"L81\");\n\n // Set recovery phase as started\n hasRecoveryPhaseStarted = true;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address. Will revert if\n * recovery phase has not started yet or if the contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) external onlyOwner {\n // Ensure recovery phase has started\n require(hasRecoveryPhaseStarted, \"L82\");\n\n // Create a reference to token's contract\n IERC20 tokenContract = IERC20(tokenAddress);\n\n // Ensure there is enough tokens to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L83\");\n\n // Transfer the recovered token amount to the sender (owner)\n tokenContract.safeTransfer(msg.sender, amount);\n }\n\n /**\n * @notice Compute the total amount of LDY rewards that a given account is eligible to.\n * @dev Note: This function neither considers vesting nor already claimed rewards.\n * @param account The account to compute the eligible rewards of.\n * @return The total amount of LDY rewards that the account is eligible to.\n */\n function eligibleRewardsOf(address account) public view returns (uint256) {\n // Compute account's lock weight\n uint256 lockerWeight = accountsLocks[account].amount * accountsLocks[account].duration;\n\n // Compute amount of LDY that this locker is eligible to\n if (maxWeight == 0) return 0;\n else return (maxDistributedLDY * lockerWeight) / maxWeight;\n }\n\n /**\n * @notice Allows locking a specified amount of underlying tokens for a given duration.\n * By locking, an account became eligible to a portion of the distributed LDY rewards.\n * @dev This function proxies LToken.deposit()\n * @dev Lockers can extend their lock duration by calling this function again with a\n * greater duration and 0 as amount.\n * @param amount Amount of underlying tokens to lock.\n * @param duration Duration of the lock (in months).\n */\n function lock(uint256 amount, uint8 duration) external whenNotPaused {\n // Ensure Deposit phase has not ended yet\n require(!hasDepositPhaseEnded, \"L84\");\n\n // Ensure account hasn't already unlocked a past lock\n require(!accountsLocks[msg.sender].hasUnlocked, \"L71\");\n\n // Ensure lock duration is in valid range\n require(duration >= minLockDuration && duration <= maxLockDuration, \"L85\");\n\n // Ensure it won't exceed the hardcap\n require(totalLocked + amount <= uint256(lockedHardCap), \"L86\");\n\n // Increase account's locked amount\n accountsLocks[msg.sender].amount += uint240(amount);\n\n // Increase total locked amount accordingly\n totalLocked += amount;\n\n // Use existing lock duration if greater than the new one\n uint8 existingDuration = accountsLocks[msg.sender].duration;\n uint8 appliedDuration = existingDuration > duration ? existingDuration : duration;\n\n // Update account's lock duration\n accountsLocks[msg.sender].duration = appliedDuration;\n\n // Update account's lock end timestamp\n accountsLocks[msg.sender].lockEndTimestamp = uint40(\n block.timestamp + uint40(appliedDuration) * 30 days\n );\n\n // Emit a Lock event\n emit Lock(msg.sender, amount, appliedDuration);\n\n // If amount is 0, skip deposit\n if (amount == 0) return;\n\n // Transfer underlyingToken from account to contract\n underlyingToken.safeTransferFrom(msg.sender, address(this), amount);\n\n // Deposit USDC in the L-Token contract\n underlyingToken.safeApprove(address(lToken), amount);\n lToken.deposit(amount);\n }\n\n /**\n * @notice Allows the caller to instaneously unlock its locked amount of underlying\n * tokens.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestUnlock() function otherwise.\n */\n function instantUnlock() external whenNotPaused safeUnlock {\n // Retrieve underlying tokens from the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.instantWithdrawal(unlockedAmount);\n\n // Transfer underlying tokens back to caller\n underlyingToken.safeTransfer(msg.sender, unlockedAmount);\n }\n\n /**\n * @notice Allows the call to request for the unlocking of its locked amount of\n * underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n */\n function requestUnlock() external payable whenNotPaused safeUnlock {\n // Put account in the unlock requests queue\n unlockRequests.push(msg.sender);\n\n // Request underlying tokens to the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.requestWithdrawal{value: msg.value}(unlockedAmount);\n }\n\n /**\n * @notice Processes queued unlock requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n */\n function processUnlockRequests() external onlyOwner {\n // Store the current request ID to process\n uint256 processedId = unlockRequestsCursor;\n\n // Loop over remaining requests\n while (processedId < unlockRequests.length) {\n // Prevent OOG by stopping request processing if there is not enough gas left\n // to continue the loop and properly end the function call.\n if (gasleft() < 45000) break;\n\n // Retrieve the request account\n address unlockAccount = unlockRequests[processedId];\n\n // Retrieve the unlocked amount\n uint256 unlockAmount = accountsLocks[unlockAccount].amount;\n\n // If the request has already been processed, skip it\n if (unlockAccount != address(0)) {\n // If the contract doesn't hold enough underlying tokens to process the request, stop here\n if (underlyingToken.balanceOf(address(this)) < unlockAmount) break;\n\n // Delete the request\n delete unlockRequests[processedId];\n\n // Transfer underlying back to account\n underlyingToken.safeTransfer(unlockAccount, unlockAmount);\n }\n\n // Increment processed request ID\n processedId++;\n }\n\n // Write back the cursor in storage\n unlockRequestsCursor = processedId;\n }\n\n /**\n * @notice Computes the amount of LDY rewards available to claim for a given account.\n * @dev This function considers vesting and already claimed rewards.\n * @param account The account to compute the available rewards of.\n * @return The amount of LDY rewards available to claim.\n */\n function availableToClaim(address account) public view returns (uint256) {\n // Compute total amount of rewards allocated to this locker\n uint256 totalEligibleRewards = eligibleRewardsOf(account);\n\n // Compute vesting duration in seconds\n uint256 vestingInSeconds = uint256(vestingDuration) * 30 days;\n\n // Compute elapsed months since claim phase started, and cap it to vesting duration\n uint256 elapsedTime = block.timestamp - claimPhaseStartTimestamp;\n if (elapsedTime > vestingInSeconds) elapsedTime = vestingInSeconds;\n\n // Compute total available to claim (proportionally to elapsed time)\n uint256 totalAvailableToClaim = (totalEligibleRewards * elapsedTime) / vestingInSeconds;\n\n // Else return net claimable (available minus already claimed)\n return totalAvailableToClaim - accountsLocks[account].claimedRewards;\n }\n\n /// @notice Allows the caller to claim its available LDY rewards.\n function claimRewards() external whenNotPaused {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L87\");\n\n // Compute claimable LDY rewards\n uint256 claimableLDY = availableToClaim(msg.sender);\n\n // Increase account claimed amount accordingly\n accountsLocks[msg.sender].claimedRewards += uint216(claimableLDY);\n\n // Transfer rewards to account\n ldyToken.safeTransfer(msg.sender, claimableLDY);\n }\n}\n" + } + }, + "settings": { + "evmVersion": "london", + "optimizer": { + "enabled": true, + "runs": 100 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/contracts/hardhat/deployments/arbitrum/solcInputs/8620a8f3d72d00ca5f27836b0fbcc97d.json b/contracts/hardhat/deployments/arbitrum/solcInputs/8620a8f3d72d00ca5f27836b0fbcc97d.json new file mode 100644 index 00000000..87c652d0 --- /dev/null +++ b/contracts/hardhat/deployments/arbitrum/solcInputs/8620a8f3d72d00ca5f27836b0fbcc97d.json @@ -0,0 +1,183 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeTo(address newImplementation) public virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../../../security/PausableUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract unpausable.\n */\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\n function __ERC20Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __ERC20Pausable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Wrapper.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../utils/SafeERC20Upgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of the ERC20 token contract to support token wrapping.\n *\n * Users can deposit and withdraw \"underlying tokens\" and receive a matching number of \"wrapped tokens\". This is useful\n * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the\n * wrapping of an existing \"basic\" ERC20 into a governance token.\n *\n * _Available since v4.2._\n *\n * @custom:storage-size 51\n */\nabstract contract ERC20WrapperUpgradeable is Initializable, ERC20Upgradeable {\n IERC20Upgradeable private _underlying;\n\n function __ERC20Wrapper_init(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n __ERC20Wrapper_init_unchained(underlyingToken);\n }\n\n function __ERC20Wrapper_init_unchained(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n require(underlyingToken != this, \"ERC20Wrapper: cannot self wrap\");\n _underlying = underlyingToken;\n }\n\n /**\n * @dev See {ERC20-decimals}.\n */\n function decimals() public view virtual override returns (uint8) {\n try IERC20MetadataUpgradeable(address(_underlying)).decimals() returns (uint8 value) {\n return value;\n } catch {\n return super.decimals();\n }\n }\n\n /**\n * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\n */\n function underlying() public view returns (IERC20Upgradeable) {\n return _underlying;\n }\n\n /**\n * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\n */\n function depositFor(address account, uint256 amount) public virtual returns (bool) {\n address sender = _msgSender();\n require(sender != address(this), \"ERC20Wrapper: wrapper can't deposit\");\n SafeERC20Upgradeable.safeTransferFrom(_underlying, sender, address(this), amount);\n _mint(account, amount);\n return true;\n }\n\n /**\n * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\n */\n function withdrawTo(address account, uint256 amount) public virtual returns (bool) {\n _burn(_msgSender(), amount);\n SafeERC20Upgradeable.safeTransfer(_underlying, account, amount);\n return true;\n }\n\n /**\n * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal\n * function that can be exposed with access control if desired.\n */\n function _recover(address account) internal virtual returns (uint256) {\n uint256 value = _underlying.balanceOf(address(this)) - totalSupply();\n _mint(account, value);\n return value;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable2Step.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "contracts/src/abstracts/base/BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"../GlobalOwnableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"../GlobalRestrictableUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../RecoverableUpgradeable.sol\";\n\n/**\n * @title BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract acts as a base for numerous contracts in this codebase,\n * minimizing code repetition and enhancing readability and maintainability.\n *\n * @dev For further details, see \"Base\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract BaseUpgradeable is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n GlobalPausableUpgradeable,\n GlobalRestrictableUpgradeable,\n RecoverableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_\n ) internal onlyInitializing {\n __UUPSUpgradeable_init();\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n __Recoverable_init_unchained();\n }\n\n function __Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/base/ERC20BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./BaseUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\n\n/**\n * @title ERC20BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract is an extension of BaseUpgradeable intended to be used\n * as a base for ERC20 tokens contracts.\n *\n * @dev For further details, see \"ERC20BaseUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract ERC20BaseUpgradeable is\n ERC20Upgradeable,\n BaseUpgradeable,\n ERC20PausableUpgradeable\n{\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param name_ The display name of the token.\n * @param symbol_ The symbol of the token.\n */\n function __ERC20Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n string memory name_,\n string memory symbol_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __ERC20_init(name_, symbol_);\n __ERC20Pausable_init_unchained();\n }\n\n function __ERC20Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and PausableUpgradeable parent contracts.\n * The GlobalPausableUpgradeable version is preferred because it checks the pause\n * state from the GlobalPause contract.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, PausableUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @dev Required override of _beforeTokenTransfer() which is implemented by both\n * ERC20PausableUpgradeable and ERC20Upgradeable parent contracts.\n * The ERC20PausableUpgradeable version is preferred because it also checks that\n * the contract is not paused before allowing the transfer.\n * @inheritdoc ERC20PausableUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n )\n internal\n virtual\n override(ERC20PausableUpgradeable, ERC20Upgradeable)\n whenNotPaused\n notBlacklisted(from)\n notBlacklisted(to)\n {\n ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalOwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {GlobalOwner} from \"../GlobalOwner.sol\";\n\n/**\n * @title GlobalOwnableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\n * contract (see GlobalOwner.sol). This design facilitates centralized management\n * of ownership for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalOwner state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalOwnableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\n /**\n * @notice The GlobalOwner contract the ownership will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalOwner private _globalOwner;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init_unchained(globalOwner_);\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\n // the initial _owner value, calling it would have no effect.\n }\n\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\n _globalOwner = GlobalOwner(globalOwner_);\n }\n\n /**\n * @notice Retrieves the address of GlobalOwner contract.\n * @return The address of the GlobalOwner contract.\n */\n function globalOwner() public view returns (address) {\n return address(_globalOwner);\n }\n\n /**\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\n * from the GlobalOwner contract instead.\n * @return The address of the owner\n */\n function owner() public view override returns (address) {\n return _globalOwner.owner();\n }\n\n /**\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function transferOwnership(address newOwner) public view override onlyOwner {\n newOwner; // Silence unused variable compiler warning\n revert(\"L8\");\n }\n\n /**\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function renounceOwnership() public view override onlyOwner {\n revert(\"L65\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalPause} from \"../GlobalPause.sol\";\n\n/**\n * @title GlobalPausableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a pause state from the specified GlobalPause\n * contract (see GlobalPause.sol). This design facilitates centralized management of\n * pause state for all the Ledgity Yield contracts.\n *\n * @dev Security measure\n * The _globalPause state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalPausableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\n /**\n * @notice The GlobalPause contract the pause state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalPause private _globalPause;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalPause_ The address of the GlobalPause contract.\n */\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n }\n\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\n _globalPause = GlobalPause(globalPause_);\n }\n\n /**\n * @notice Retrieves the address of GlobalPause contract.\n * @return The address of the GlobalPause contract.\n */\n function globalPause() public view returns (address) {\n return address(_globalPause);\n }\n\n /**\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\n * from the GlobalPause contract instead.\n * @return Whether the contract is paused or not.\n */\n function paused() public view virtual override returns (bool) {\n return _globalPause.paused();\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalRestrictableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalBlacklist} from \"../GlobalBlacklist.sol\";\n\n/**\n * @title GlobalRestrictableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a blacklist state from the specified\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\n * centralized management of a blacklist for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalBlacklist state must be set at initialization time and, for evident\n * security reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalRestrictableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalRestrictableUpgradeable is Initializable {\n /**\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalBlacklist private _globalBlacklist;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n }\n\n function __GlobalRestrictable_init_unchained(\n address globalBlacklist_\n ) internal onlyInitializing {\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\n }\n\n /**\n * @notice Retrieves the address of GlobalBlacklist contract.\n * @return The address of the GlobalBlacklist contract.\n */\n function globalBlacklist() public view returns (address) {\n return address(_globalBlacklist);\n }\n\n /**\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n */\n modifier notBlacklisted(address account) {\n require(isBlacklisted(account) == false, \"L9\");\n _;\n }\n\n /**\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n * @return Whether the account is blacklisted.\n */\n function isBlacklisted(address account) internal view returns (bool) {\n return _globalBlacklist.isBlacklisted(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/InvestUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"./GlobalPausableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"./GlobalRestrictableUpgradeable.sol\";\nimport \"./base/BaseUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../abstracts/RecoverableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {APRHistory as APRH} from \"../libs/APRHistory.sol\";\nimport {SUD} from \"../libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title InvestUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with utilities to manage an invested token,\n * users' investment periods, rewards calculations, virtual balances, and auto-compounding.\n *\n * @dev Intuition:\n * This contract primarily exists for code splitting and reusability. It unburdens the\n * LToken contract code, making it easier to understand and maintain.\n *\n * This contract is generic because it may be used in the LDYStaking contract in the future.\n *\n * @dev Definitions:\n * - Investment: The act of depositing or investing tokens into the contract.\n * - Investment period: Time between the last invested amount change and the present.\n * - Virtual balance: Temporary storage for account rewards, used when those can't be\n * distributed between investment periods.\n * - Rewards redirection: Mechanism allowing an account to redirect its rewards to another.\n *\n * @dev Derived contract must:\n * - Set invested token during initialization\n * - Implement _investmentOf() function\n * - (optionally) Implement _distributeRewards() function\n *\n * @dev For further details, see \"InvestmentUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract InvestUpgradeable is BaseUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using APRH for APRH.Pack[];\n\n /**\n * @notice Represents an account's investment period.\n * @param timestamp The timestamp of the most recent rewards distribution.\n * @param ref The reference of the last APR checkpoint at that timestamp.\n */\n struct InvestmentPeriod {\n uint40 timestamp; // Supports dates up to 20/02/36812\n APRH.Reference ref;\n }\n\n /**\n * @notice Represents the investment details of an account.\n * @param period The current investment period of the account.\n * @param virtualBalance May hold a part of account rewards until they are claimed.\n */\n struct AccountDetails {\n InvestmentPeriod period;\n uint256 virtualBalance;\n }\n\n /// @notice Holds a reference to the invested token's contract.\n IERC20Upgradeable private _invested;\n\n /// @notice Holds investment details of each account.\n mapping(address => AccountDetails) internal accountsDetails;\n\n /// @notice Holds an history of the APR value over time (see APRHistory.sol).\n APRH.Pack[] private _aprHistory;\n\n /// @notice Holds active rewards redirections in both from->to and to->from[] ways.\n mapping(address => address) public rewardsRedirectsFromTo;\n mapping(address => address[]) public rewardsRedirectsToFrom;\n\n /// @notice Is used to prevent infinite loop in _beforeInvestmentChange().\n bool private _isClaiming;\n\n /**\n * @notice Emitted to inform listeners about a change in the APR's value.\n * @param newAPRUD7x3 The new APR in UD7x3 format.\n */\n event APRChangeEvent(uint16 newAPRUD7x3);\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param invested_ The address of the invested token contract.\n */\n function __Invest_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address invested_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __Invest_init_unchained(invested_);\n }\n\n function __Invest_init_unchained(address invested_) internal onlyInitializing {\n // Set invested token\n _invested = IERC20Upgradeable(invested_);\n\n // Define initial APR to 0%. This would prevent getAPR() from reverting because\n // of an empty APR history\n _aprHistory.setAPR(0);\n }\n\n /**\n * @notice Retrieves the reference to the invested token contract.\n * @return The reference to the invested token contract.\n */\n function invested() public view returns (IERC20Upgradeable) {\n return _invested;\n }\n\n /**\n * @notice Updates the investment APR. Restricted to owner.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(uint16 aprUD7x3) public onlyOwner {\n _aprHistory.setAPR(aprUD7x3);\n emit APRChangeEvent(aprUD7x3);\n }\n\n /**\n * @notice Retrieves the most recently set APR.\n * @return The current APR in UD7x3 format.\n */\n function getAPR() public view returns (uint16) {\n return _aprHistory.getAPR();\n }\n\n /**\n * @notice Enables redirection of rewards from one account to another.\n * @param from The address of the account to redirect rewards from.\n * @param to The address of the account to redirect rewards to.\n */\n function startRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure the address is not already redirecting rewards\n require(rewardsRedirectsFromTo[from] == address(0), \"L62\");\n\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L12\");\n require(to != address(0), \"L13\");\n\n // Ensure 'from' and 'to' addresses are distinct\n require(from != to, \"L14\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L15\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Activate rewards redirection\n rewardsRedirectsFromTo[from] = to;\n rewardsRedirectsToFrom[to].push(from);\n }\n\n /**\n * @notice Disable an active rewards redirection.\n * @param from The address of the account to stop redirecting rewards from.\n * @param to The address of the account to stop redirecting rewards to.\n */\n function stopRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L16\");\n require(to != address(0), \"L17\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L18\");\n\n // Ensure a rewards redirection was active\n require(rewardsRedirectsFromTo[from] == to, \"L19\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Retrieve 'from' index in the redirection array of 'to'\n int256 fromIndex = -1;\n for (uint256 i = 0; i < rewardsRedirectsToFrom[to].length; i++) {\n if (rewardsRedirectsToFrom[to][i] == from) {\n fromIndex = int256(i);\n break;\n }\n }\n\n // fromIndex should never be -1 at this point\n assert(fromIndex >= 0);\n\n // Deactivate rewards redirection\n rewardsRedirectsFromTo[from] = address(0);\n rewardsRedirectsToFrom[to][uint256(fromIndex)] = rewardsRedirectsToFrom[to][\n rewardsRedirectsToFrom[to].length - 1\n ];\n rewardsRedirectsToFrom[to].pop();\n }\n\n /**\n * @notice Retrieves the total amount of tokens invested by the given account.\n * @dev Derived contracts must implement this function.\n * @param account The account to get the investment of.\n * @return The total amount of tokens invested by the given account.\n */\n function _investmentOf(address account) internal view virtual returns (uint256);\n\n /**\n * @notice Distributes a specified amount of rewards to a given account.\n * @dev Derived contracts may optionally implement this function.\n * @dev Implementations must return true to indicate a successful distribution, and\n * false otherwise. If it returns false, the rewards will be added to the account's\n * virtual balance, in order to be claimed later.\n * @param account The account to claim the rewards of.\n * @param amount The amount of rewards to claim.\n * @return Whether the rewards distribution was successfull.\n */\n function _distributeRewards(address account, uint256 amount) internal virtual returns (bool) {\n account; // Silence unused variables warning\n amount;\n return false;\n }\n\n /**\n * @notice Computes the rewards accrued over a specified period of time, based on a\n * given APR and amount of invested tokens.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param beginTimestamp The moment the period commenced.\n * @param endTimestamp The moment the period concluded.\n * @param aprUD7x3 The APR during this period, in UD7x3 format.\n * @param investedAmount The amount of tokens deposited/invested during the period.\n * @return The amount of rewards generated during the period.\n */\n function _calculatePeriodRewards(\n uint40 beginTimestamp,\n uint40 endTimestamp,\n uint16 aprUD7x3,\n uint256 investedAmount\n ) internal view returns (uint256) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Compute the number of elapsed years\n uint256 elapsedTimeSUD = SUD.fromInt(endTimestamp - beginTimestamp, d);\n uint256 elapsedYearsSUD = (elapsedTimeSUD * SUD.fromInt(1, d)) / SUD.fromInt(365 days, d);\n\n // Compute the growth in invested amount (thanks to rewards)\n uint256 aprSUD = SUD.fromRate(aprUD7x3, d);\n uint256 growthSUD = (elapsedYearsSUD * aprSUD) / SUD.fromInt(1, d);\n\n // Compute and return the rewards\n uint256 investedAmountSUD = SUD.fromAmount(investedAmount, d);\n uint256 rewardsSUD = (investedAmountSUD * growthSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(rewardsSUD, d);\n }\n\n /**\n * @notice Computes the sum of given account's invested amount, plus invested amount\n * of all accounts that recursively redirect rewards to this account.\n * @param account The account to calculate the deep investment of.\n * @return deepInvestedAmount The deep invested amount.\n */\n function _deepInvestmentOf(address account) internal view returns (uint256 deepInvestedAmount) {\n // Consider account's direct investment\n deepInvestedAmount += _investmentOf(account);\n\n // But also the deep investments of all accounts redirecting rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n deepInvestedAmount += _deepInvestmentOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Computes the amount of unclaimed/undistributed rewards of a given account.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param account The account to calculate the unclaimed rewards of.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n * @return rewards The amount of unclaimed/undistributed rewards of the given account.\n */\n function _rewardsOf(\n address account,\n bool autocompound\n ) internal view returns (uint256 rewards) {\n // Retrieve account's investment details\n AccountDetails memory details = accountsDetails[account];\n\n // Retrieve account's deep invested amount\n uint256 investedAmount = _deepInvestmentOf(account);\n\n // Return 0 if the account has never invested or has no invested amount\n if (details.period.timestamp == 0 || investedAmount == 0) return 0;\n\n // Retrieve reference and data of APR checkpoint at which started investment period\n APRH.Reference memory currRef = details.period.ref;\n APRH.CheckpointData memory currCheckpoint = _aprHistory.getDataFromReference(currRef);\n\n // Retrieve reference of latest APR checkpoint\n APRH.Reference memory latestRef = _aprHistory.getLatestReference();\n\n // 1) Fill rewards with virtual balance (rewards not claimed/distributed yet)\n // See \"InvestUpgradeable > Yield calculation > 1)\" section of the whitepaper\n rewards = details.virtualBalance;\n\n // If start checkpoint is not the latest one\n if (!APRH.eq(currRef, latestRef)) {\n // Retrieve reference and data of APR checkpoint that comes after start checkpoint\n APRH.Reference memory nextRef = APRH.incrementReference(currRef);\n APRH.CheckpointData memory nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // 2) Calculate rewards from investment period start to next checkpoint\n // See \"InvestUpgradeable > Yield calculation > 2)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n\n // 3) Calculate rewards for each crossed pair of checkpoints\n // See \"InvestUpgradeable > Yield calculation > 3)\" section of the whitepaper\n while (true) {\n // Set next checkpoint as the current one\n currRef = nextRef;\n currCheckpoint = nextCheckpoint;\n\n // Break if current checkpoint is the latest one\n if (APRH.eq(currRef, latestRef)) break;\n\n // Else, retrieve the new next checkpoint\n nextRef = APRH.incrementReference(currRef);\n nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // Calculate rewards between the current pair of checkpoints\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n\n // 4) Calculate rewards from the latest checkpoint to now\n // See \"InvestUpgradeable > Yield calculation > 4)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n } else {\n // 2.bis) Calculate rewards from investment period start to now\n // See \"InvestUpgradeable > Yield calculation > 2.bis)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n }\n\n /**\n * @notice Recursively resets the investment period of the specified account and of\n * all accounts that directly or indirectly redirect rewards to this account.\n * @param account The account to deeply reset the investment period of.\n */\n function _deepResetInvestmentPeriodOf(address account) internal {\n // Reset account investment period timestamp and APR checkpoint to latest ones\n accountsDetails[account].period.timestamp = uint40(block.timestamp);\n accountsDetails[account].period.ref = _aprHistory.getLatestReference();\n\n // Also reset the ones of all accounts that recursively redirect rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n _deepResetInvestmentPeriodOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Hook to be invoked before the invested amount of an account changes. It\n * ensures that rewards are distributed and that account's investment period is reset.\n * @param account The account whose invested amount is going to change.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n */\n function _beforeInvestmentChange(address account, bool autocompound) internal {\n // This hook is called inside LToken._beforeTokenTransfer() and as new tokens are\n // minted in LToken._distributeRewards(), this guards against infinite loop.\n if (_isClaiming) return;\n\n // LToken._beforeTokenTransfer() calls this hook for both involved addresses.\n // As first call will treat both addresses, the second call would be redundant.\n // Therefore, we skip accounts already processed in this block to save up some gas.\n if (accountsDetails[account].period.timestamp == uint40(block.timestamp)) return;\n\n // If account redirects its rewards\n address redirectRewardsTo = rewardsRedirectsFromTo[account];\n if (redirectRewardsTo != address(0)) {\n // Call hook on redirection target (this will indirectly reset the investment\n // of this source account) and return\n _beforeInvestmentChange(redirectRewardsTo, autocompound);\n return;\n }\n\n // Else, compute account's undistributed/unclaimed rewards\n uint256 rewards = _rewardsOf(account, autocompound);\n\n // If there are some rewards\n if (rewards > 0) {\n // Try to distribute rewards to account\n _isClaiming = true;\n bool distributed = _distributeRewards(account, rewards);\n _isClaiming = false;\n\n // If rewards have not been distributed, accumulate them in account's virtual balance\n if (!distributed) accountsDetails[account].virtualBalance = rewards;\n }\n\n // Finally, deeply reset investment period of the account\n _deepResetInvestmentPeriodOf(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/RecoverableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Conracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title RecoverableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with helper functions allowing the recovery of\n * assets accidentally sent to them.\n *\n * @dev Where are utilities Ether, ERC721, etc.?\n * This abstract contract currently supports only ERC20 tokens. Derived contracts\n * in this codebase currently do not implement the necessary functions to receive Ether\n * or ERC721/ERC1155 tokens, so no recovery functions are provided for these assets.\n *\n * @dev For further details, see \"RecoverableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init(globalOwner_);\n __Recoverable_init_unchained();\n }\n\n function __Recoverable_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Recovers a specified amount of a given token address. Will fail if the\n * contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\n // Ensure the specified amount is not zero\n require(amount > 0, \"L10\");\n\n // Create a reference to token's contract\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\n\n // Ensure there is enough token to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L11\");\n\n // Transfer the recovered token amount to the sender\n tokenContract.safeTransfer(_msgSender(), amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/GenericERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n\n/**\n * @notice Used for testing purposes only, and used to generate ABIs for Wagmi contracts calls.\n * It represents:\n * - a FIAT-based stablecoin when used to test the LToken contract,\n * - the $LDY token when used to test the LDYStaking contract.\n * This contract accept decimals as constructor argument, so it can be used to to\n * easily test different decimals scenarios.\n */\ncontract GenericERC20 is ERC20, ERC20Burnable {\n uint8 private _decimals;\n\n constructor(string memory name, string memory symbol, uint8 decimals_) ERC20(name, symbol) {\n _decimals = decimals_;\n }\n\n function mint(uint256 amount) public {\n _mint(msg.sender, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n\n /**\n * Used in tests to test different decimals scenarios.\n */\n function setDecimals(uint8 decimals_) public {\n _decimals = decimals_;\n }\n}\n" + }, + "contracts/src/GlobalBlacklist.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalBlacklist\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global mapping of blacklisted accounts shared by all contracts of the\n * Ledgity Yield codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\n * and getter functions to easily check against this global blacklist.\n *\n * @dev For further details, see \"GlobalBlacklist\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\n /**\n * @notice Mapping of accounts to their blacklist status.\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\n */\n mapping(address => bool) private _list;\n\n /// @dev Emitted when `account` is blacklisted.\n event Blacklisted(address account);\n\n /// @dev Emitted when `account` is unblacklisted.\n event Unblacklisted(address account);\n\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @notice Adds a given account to the blacklist.\n * @param account The account's address to be blacklisted.\n */\n function blacklist(address account) external onlyOwner {\n require(account != address(0), \"L20\");\n _list[account] = true;\n emit Blacklisted(account);\n }\n\n /**\n * @notice Removes a given account from the blacklist.\n * @param account The account's address to be un-blacklisted.\n */\n function unBlacklist(address account) external onlyOwner {\n _list[account] = false;\n emit Unblacklisted(account);\n }\n\n /**\n * @notice Checks whether a given account is blacklisted.\n * @param account Address of the account to check.\n * @return 'true' if the account is blacklisted, 'false' otherwise\n */\n function isBlacklisted(address account) external view returns (bool) {\n // Gas optimization: Avoid accessing storage if account is the zero address\n // (e.g, during a mint or a burn of tokens)\n if (account == address(0)) return false;\n\n // Else, return current account's blacklist status\n return _list[account];\n }\n}\n" + }, + "contracts/src/GlobalOwner.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {Ownable2StepUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\n/**\n * @title GlobalOwner\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds the address of a global owner account shared by all contracts of the\n * Ledgity Yield's codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\n * owner() function that retrieves the owner's address from this contract instead.\n *\n * @dev For further details, see \"GlobalOwner\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n */\n function initialize() public initializer {\n __Ownable2Step_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n}\n" + }, + "contracts/src/GlobalPause.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalPause\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global pause state shared by all contracts of the Ledgity Yield\n * codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\n * paused() function that retrieves the pause state from this contract instead.\n *\n * @dev For further details, see \"GlobalPause\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalPause is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n PausableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\n * but restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n}\n" + }, + "contracts/src/interfaces/ITransfersListener.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\ninterface ITransfersListener {\n function onLTokenTransfer(address from, address to, uint256 amount) external;\n}\n" + }, + "contracts/src/LDY.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n\n/**\n * @title LDY\n * @author Lila Rest (lila@ledgity.com)\n * @dev The $LDY is the utility and governance token of the entire Ledgity ecosystem.\n *\n * This contract has been kept as minimal as possible to enforce stakeholders safety\n * but also to pave the way for sensitive use cases like cross-chain bridging, use in\n * governance scenarios, and compatibility with 3rd party DApps.\n *\n * It is non-upgradeable, non-ownable, non-pausable, non-mintable, and non-restrictable.\n * It implements nothing more than what is provided by its OpenZepellin ancestors.\n *\n * Moreover, to eliminate the need for ownership and complex vesting functions, the\n * entire supply is minted at deployment-time. Vesting of allocated tokens is then\n * managed via Sablier streams that anyone can verify on this page:\n * https://docs.ledgity.finance/tokenomics/vesting-proofs\n *\n * Specifications:\n * - Name: Ledgity Token\n * - Symbol: LDY\n * - Decimals: 18\n * - Total supply: 75,000,000\n *\n * @custom:security-contact security@ledgity.com\n */\ncontract LDY is ERC20, ERC20Burnable {\n constructor() ERC20(\"Ledgity Token\", \"LDY\") {\n _mint(msg.sender, 75_000_000 * 10 ** decimals());\n }\n}\n" + }, + "contracts/src/LDYStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {BaseUpgradeable} from \"./abstracts/base/BaseUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title LDYStaking\n * @custom:security-contact security@ledgity.com\n *\n * @dev This contract implements tierOf() function from LDYStaking as it's the only\n * one the LToken contract relies on.\n *\n * @custom:security-contact security@ledgity.com\n */\ncontract LDYStaking is BaseUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Represents a user staking info in array.\n * @param stakedAmount Amount of the stake.\n * @param unStakeAt Unstake at.\n * @param duration Staking period in seconds.\n * @param rewardPerTokenPaid Reward per token paid.\n * @param rewards Rewards to be claimed.\n */\n struct StakingInfo {\n uint256 stakedAmount;\n uint256 unStakeAt;\n uint256 duration;\n uint256 rewardPerTokenPaid;\n uint256 rewards;\n }\n\n /**\n * @notice Represent duration and multiplier per each stake option.\n * @param duration Staking period in seconds.\n * @param multiplier Token weight\n */\n struct StakeDurationInfo {\n uint256 duration;\n uint256 multiplier;\n }\n\n /// @notice Decimals of multiplier\n uint256 public constant MULTIPLIER_BASIS = 1e4;\n\n /// @notice Stake and Reward token.\n IERC20Upgradeable public stakeRewardToken;\n\n /// @notice Minimal stake duration for perks.\n uint256 public stakeDurationForPerks;\n\n /// @notice Minimal stake amount for perks.\n uint256 public stakeAmountForPerks;\n\n /// @notice Stake durations info array.\n StakeDurationInfo[] public stakeDurationInfos;\n\n /// @notice Duration of the rewards (in seconds).\n uint256 public rewardsDuration;\n\n /// @notice Timestamp of when the rewards finish.\n uint256 public finishAt;\n\n /// @notice Timestamp of the reward updated.\n uint256 public lastUpdateTime;\n\n /// @notice Reward per second(total rewards / duration).\n uint256 public rewardRatePerSec;\n\n /// @notice Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\n uint256 public rewardPerTokenStored;\n\n /// @notice Total staked amounts.\n uint256 public totalStaked;\n\n // Total staked amounts with multiplier applied\n uint256 public totalWeightedStake;\n\n /// @notice User stakingInfo map, user address => array of the staking info\n mapping(address => StakingInfo[]) public userStakingInfo;\n\n /// @notice Total rewards amount.\n uint256 public totalRewards;\n\n /**\n * @notice Emitted when users stake token\n * @param user User address\n * @param stakeIndex Latest index of user staking pool\n * @param amount Staked amount\n */\n event Staked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users unstake token\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param amount Staked amount\n */\n event Unstaked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users claim rewards\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param reward Reward token amount\n */\n event RewardPaid(address indexed user, uint256 stakeIndex, uint256 reward);\n\n /**\n * @notice Emitted when admin add rewards.\n * @param rewardAmount Reward amount added by admin.\n * @param rewardPerSec RewardRatePerSec updated.\n */\n event NotifiedRewardAmount(uint256 rewardAmount, uint256 rewardPerSec);\n\n /**\n * @notice Holds a mapping of addresses that default to the highest staking tier.\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\n */\n mapping(address => bool) public highTierAccounts;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\n * @dev This function is intended for setting initial values for the contract's state variables.\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param stakeRewardToken_ The address of stake and reward token(LDY token).\n * @param stakeDurationInfos_ Available Staking Durations.\n * @param stakeDurationForPerks_ Minimal staking duration for perks.\n * @param stakeAmountForPerks_ Minimal staking amount for perks.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address stakeRewardToken_,\n StakeDurationInfo[] memory stakeDurationInfos_,\n uint256 stakeDurationForPerks_,\n uint256 stakeAmountForPerks_\n ) public initializer {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n stakeRewardToken = IERC20Upgradeable(stakeRewardToken_);\n uint stakeDurationInfosLength = stakeDurationInfos_.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n stakeDurationInfos.push(stakeDurationInfos_[i]);\n }\n stakeDurationForPerks = stakeDurationForPerks_;\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n // --------------------\n // MUTATIVE FUNCTIONS\n // --------------------\n\n /**\n * @notice Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\n * @dev Emits a `Staked` event upon successful staking.\n * @param amount The amount of tokens to stake.\n * @param stakeDurationIndex The Index of stakeDurationInfos array.\n */\n function stake(\n uint256 amount,\n uint8 stakeDurationIndex\n ) external nonReentrant whenNotPaused notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(stakeDurationIndex <= stakeDurationInfos.length - 1, \"Invalid staking period\");\n\n _updateReward(address(0), 0);\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[stakeDurationIndex];\n StakingInfo memory stakingInfo = StakingInfo({\n stakedAmount: amount,\n unStakeAt: block.timestamp + stakeDurationInfo.duration,\n duration: stakeDurationInfo.duration,\n rewardPerTokenPaid: rewardPerTokenStored,\n rewards: 0\n });\n\n // check whether account is eligible for benefit from the protocol\n if (stakeDurationInfo.duration >= stakeDurationForPerks && amount >= stakeAmountForPerks) {\n highTierAccounts[_msgSender()] = true;\n }\n\n userStakingInfo[_msgSender()].push(stakingInfo);\n\n uint256 stakeIndex = userStakingInfo[_msgSender()].length - 1;\n uint256 weightedStake = (amount * stakeDurationInfo.multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake += weightedStake;\n totalStaked += amount;\n\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit Staked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Withdraw staked tokens after stakeDuration has passed.\n * @dev Emits a `Unstaked` event upon successful withdrawal.\n * On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\n * @param amount The amount of tokens to withdraw.\n * @param stakeIndex The index of user staking pool\n */\n function unstake(\n uint256 amount,\n uint256 stakeIndex\n ) external nonReentrant notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n require(\n block.timestamp >= userStakingInfo[_msgSender()][stakeIndex].unStakeAt,\n \"Cannot unstake during staking period\"\n );\n require(\n amount <= userStakingInfo[_msgSender()][stakeIndex].stakedAmount,\n \"Insufficient unstake amount\"\n );\n\n _updateReward(_msgSender(), stakeIndex);\n\n uint256 multiplier = _getMultiplier(userStakingInfo[_msgSender()][stakeIndex].duration);\n\n uint256 currentWeightedStake = (amount * multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake -= currentWeightedStake;\n\n totalStaked -= amount;\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount -= amount;\n\n // check whether account is eligible for benefit from the protocol\n if (\n userStakingInfo[_msgSender()][stakeIndex].duration >= stakeDurationForPerks &&\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount < stakeAmountForPerks\n ) {\n highTierAccounts[_msgSender()] = false;\n }\n\n // remove staking info from array on full withdrawal\n if (userStakingInfo[_msgSender()][stakeIndex].stakedAmount == 0) {\n _claimReward(_msgSender(), stakeIndex);\n\n userStakingInfo[_msgSender()][stakeIndex] = userStakingInfo[_msgSender()][\n userStakingInfo[_msgSender()].length - 1\n ];\n userStakingInfo[_msgSender()].pop();\n }\n stakeRewardToken.safeTransfer(_msgSender(), amount);\n\n emit Unstaked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Claim pending rewards.\n * @dev Emits a `RewardPaid` event upon successful reward claim.\n * @param stakeIndex The index of user staking pool.\n */\n function getReward(uint256 stakeIndex) external nonReentrant notBlacklisted(_msgSender()) {\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n _updateReward(_msgSender(), stakeIndex);\n _claimReward(_msgSender(), stakeIndex);\n }\n\n // --------------------\n // ADMIN CONFIGURATION\n // --------------------\n\n /**\n * @notice Update Rewards Duration.\n * @dev Only callable by owner, and setting available only after rewards period.\n * @param duration New reward duration in seconds.\n */\n function setRewardsDuration(uint256 duration) external onlyOwner {\n require(finishAt < block.timestamp, \"reward duration is not finished\");\n rewardsDuration = duration;\n }\n\n /**\n * @notice Update stakeDurationForPerks\n * @dev Only callable by owner.\n * @param stakeDurationForPerks_ New stakeDurationForPerks.\n */\n function setStakeDurationForPerks(uint256 stakeDurationForPerks_) external onlyOwner {\n stakeDurationForPerks = stakeDurationForPerks_;\n }\n\n /**\n * @notice Update stakeAmountForPerks\n * @dev Only callable by owner.\n * @param stakeAmountForPerks_ New stakeDurationForPerks.\n */\n function setStakeAmountForPerks(uint256 stakeAmountForPerks_) external onlyOwner {\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n /**\n * @notice Push stakeDurationInfo\n * @dev Only callable by owner.\n */\n function pushStakeDurationInfo(StakeDurationInfo memory durationInfo) external onlyOwner {\n stakeDurationInfos.push(durationInfo);\n }\n\n /**\n * @notice Notify the contract about the amount of rewards to be distributed and update reward parameters.\n * @dev Only callable by owner.\n * @param amount The amount of reward to be distributed.\n */\n function notifyRewardAmount(uint256 amount) external onlyOwner {\n require(rewardsDuration > 0, \"rewards duration is not set\");\n require(amount > 0, \"amount = 0\");\n\n _updateReward(address(0), 0);\n\n if (block.timestamp >= finishAt) {\n rewardRatePerSec = amount / rewardsDuration;\n } else {\n uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatePerSec;\n rewardRatePerSec = (amount + remainingRewards) / rewardsDuration;\n }\n\n require(rewardRatePerSec > 0, \"reward rate = 0\");\n require(\n rewardRatePerSec <=\n (stakeRewardToken.balanceOf(address(this)) + amount - totalStaked) /\n rewardsDuration,\n \"reward amount > balance\"\n );\n\n finishAt = block.timestamp + rewardsDuration;\n lastUpdateTime = block.timestamp;\n\n totalRewards += amount;\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit NotifiedRewardAmount(amount, rewardRatePerSec);\n }\n\n // --------------------\n // VIEW FUNCTIONS\n // --------------------\n\n /**\n * @notice Get the last time when rewards were applicable for the specified reward token.\n * @return Timestamp of the most recent rewards calculation.\n */\n function lastTimeRewardApplicable() public view returns (uint256) {\n return _min(finishAt, block.timestamp);\n }\n\n /**\n * @notice Calculate the reward per token for a given reward token.\n * @return Current reward per token.\n */\n function rewardPerToken() public view returns (uint256) {\n if (totalStaked == 0) {\n return rewardPerTokenStored;\n }\n\n return\n rewardPerTokenStored +\n ((rewardRatePerSec * (lastTimeRewardApplicable() - lastUpdateTime) * 1e18) /\n totalWeightedStake);\n }\n\n /**\n * @notice Calculate the user's stake pool earnings\n * @param account Address of the user.\n * @param stakeIndex Index of the stakePool\n * @return Return earned amounts\n */\n function earned(address account, uint256 stakeIndex) public view returns (uint256) {\n StakingInfo memory userInfo = userStakingInfo[account][stakeIndex];\n uint256 multiplier = _getMultiplier(userInfo.duration);\n uint256 weightedAmount = (userInfo.stakedAmount * multiplier) / MULTIPLIER_BASIS;\n uint256 rewardsSinceLastUpdate = ((weightedAmount *\n (rewardPerToken() - userInfo.rewardPerTokenPaid)) / 1e18);\n return rewardsSinceLastUpdate + userInfo.rewards;\n }\n\n /**\n * @notice Get the earned rewards array for a user.\n * @param account Address of the user.\n * @return Return earned rewards array for a user.\n */\n function getEarnedUser(address account) public view returns (uint256[] memory) {\n uint256 numberOfPools = userStakingInfo[account].length;\n uint256[] memory earnedArray = new uint256[](numberOfPools);\n for (uint256 index; index < numberOfPools; index++) {\n earnedArray[index] = earned(account, index);\n }\n return earnedArray;\n }\n\n /**\n * @dev tierOf() function that always return that the given account is not\n * elligible to any LDY staking tier, except if the account is in the\n * highTierAccounts mapping.\n * @param account The account to check the tier of.\n */\n function tierOf(address account) public view returns (uint256 tier) {\n if (highTierAccounts[account]) return 3;\n return 0;\n }\n\n /**\n * @notice Get User Stake Data.\n * @param account The address of user.\n * @return StakingInfo array.\n */\n function getUserStakes(address account) external view returns (StakingInfo[] memory) {\n return userStakingInfo[account];\n }\n\n /**\n * @notice Get StakeDurationInfo.\n * @param index Index of StakeDurationInfos.\n * @return StakeDurationInfo.\n */\n function getStakeDurationInfo(uint256 index) external view returns (StakeDurationInfo memory) {\n require(stakeDurationInfos.length - 1 >= index, \"wrong index\");\n return stakeDurationInfos[index];\n }\n\n /**\n * @notice Send rewards to user.\n * @dev This is private function, called by getReward function.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _claimReward(address account, uint256 stakeIndex) private {\n uint256 reward = userStakingInfo[account][stakeIndex].rewards;\n\n if (reward > 0) {\n userStakingInfo[account][stakeIndex].rewards = 0;\n totalRewards -= reward;\n stakeRewardToken.safeTransfer(account, reward);\n emit RewardPaid(account, stakeIndex, reward);\n }\n }\n\n /**\n * @notice Calculate and update user rewards per stakeIndex.\n * @dev this is private function, called by stake, unstake, getRewards, and notifyRewardAmount functions.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _updateReward(address account, uint256 stakeIndex) private {\n rewardPerTokenStored = rewardPerToken();\n lastUpdateTime = lastTimeRewardApplicable();\n\n if (account != address(0)) {\n userStakingInfo[account][stakeIndex].rewards = earned(account, stakeIndex);\n userStakingInfo[account][stakeIndex].rewardPerTokenPaid = rewardPerTokenStored;\n }\n }\n\n /**\n * @notice Get multiplier from stakeDurationInfo based on duration\n * @param duration Stake Duration\n */\n function _getMultiplier(uint256 duration) private view returns (uint256) {\n uint256 stakeDurationInfosLength = stakeDurationInfos.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[i];\n if (duration == stakeDurationInfo.duration) {\n return stakeDurationInfo.multiplier;\n }\n }\n return 0;\n }\n\n /**\n * @notice Take minimum value between x and y.\n */\n function _min(uint256 x, uint256 y) private pure returns (uint256) {\n return x <= y ? x : y;\n }\n}\n" + }, + "contracts/src/libs/APRHistory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n/**\n * @title APRHistory\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This library offers utilities to efficiently maintain the history of an\n * on-chain APR (Annual Percentage Rate) state. Each entry in this history is called\n * a \"checkpoint\".\n *\n * @dev Intuition:\n * Each checkpoint in an APR history consists of two data:\n * - the creation timestamp\n * - the APR at that time\n *\n * Given that reading and writing to storage slots are among the most costly operations\n * in Solidity, this library provides a way to store those data in a way that minimizes\n * the number of used storage slots.\n *\n * Instead of storing each checkpoint in a separate storage slot, this library\n * facilitates the packing of up to 4 checkpoints in a single storage slot.\n *\n * @dev Definitions:\n * - Checkpoint: A record of an APR change\n * - Pack: A collection of 4 checkpoints stored in a single storage slot\n * - History: A dynamic array of packs\n * - Reference: A storage pointer to a checkpoint in the APR history\n * - CheckpointData: An in-memory representation of a checkpoint data\n *\n * @dev Value limitation:\n * This library can accommodate APRs only up to 65.536%. This is however sufficient for\n * APR in LToken contract, which is expected to remain below 10%.\n *\n * @dev For further details, see \"APRHistory\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary APRHistory {\n /**\n * @notice Represents data of a checkpoint extracted from the on-chain history.\n * For on-chain representation see \"Pack\" struct.\n * @param aprUD7x3 APR in UD7x3 format (e.g., 12345 = 12.345%).\n * @param timestamp Timestamp of the checkpoint's creation.\n */\n struct CheckpointData {\n uint16 aprUD7x3; // Allows up to 65.536%\n uint40 timestamp; // Supports dates up to 20/02/36812\n }\n\n /**\n * @notice Represents how APR checkpoints are stored on chain. Each pack can contain\n * the data 4 checkpoints. Packs are then stored in a dynamic array (the history).\n * @param aprsUD7x3 Array of checkpoints' APRs.\n * @param timestamps Array of checkpoints' timestamps.\n * @param cursor Index of the next checkpoint to be written.\n */\n struct Pack {\n uint16[4] aprsUD7x3;\n uint40[4] timestamps;\n uint32 cursor;\n }\n\n /**\n * @notice Represents a storage pointer to a specific checkpoint in the history.\n * @param packIndex Index of the pack the checkpoint belongs to.\n * @param cursorIndex Index of the checkpoint in this pack (between 0 and 3).\n */\n struct Reference {\n uint256 packIndex;\n uint32 cursorIndex;\n }\n\n /**\n * @notice Compares two checkpoints references.\n * @param ref1 The first reference to compare.\n * @param ref2 The second reference to compare.\n * @return Whether the two references points to the same checkpoint.\n */\n function eq(Reference memory ref1, Reference memory ref2) external pure returns (bool) {\n return ref1.packIndex == ref2.packIndex && ref1.cursorIndex == ref2.cursorIndex;\n }\n\n /**\n * @notice Returns the reference of the checkpoint that should come right after the\n * referenced checkpoint in the APR history.\n * @param ref The reference to be incremented.\n * @return The incremented reference.\n */\n function incrementReference(Reference memory ref) public pure returns (Reference memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L1\");\n\n // If the given ref is the last slot in its pack, return ref of next pack's first slot\n if (ref.cursorIndex == 3) return Reference(ref.packIndex + 1, 0);\n //\n // Else, return ref of next slot in current pack\n else return Reference(ref.packIndex, ref.cursorIndex + 1);\n }\n\n /**\n * @notice Extracts checkpoint data from a given reference and in APR history.\n * @param self The APR history to extract the checkpoint from.\n * @param ref The reference of the checkpoint data to extract.\n * @return The extracted checkpoint's data.\n */\n function getDataFromReference(\n Pack[] storage self,\n Reference memory ref\n ) public view returns (CheckpointData memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L2\");\n\n // Ensure pack index of the given ref exists in history\n require(ref.packIndex < self.length, \"L3\");\n\n // Retrieve pack data from history\n Pack memory pack = self[ref.packIndex];\n\n // Ensure cursor index of the given ref has been written\n require(ref.cursorIndex < pack.cursor, \"L4\");\n\n // Build and return the checkpoint data\n return\n CheckpointData({\n aprUD7x3: pack.aprsUD7x3[ref.cursorIndex],\n timestamp: pack.timestamps[ref.cursorIndex]\n });\n }\n\n /**\n * @notice Retrieves the reference to the most recently added checkpoint in the APR history.\n * @param self The history to extract the reference from.\n * @return The reference of the latest checkpoint.\n */\n function getLatestReference(Pack[] storage self) public view returns (Reference memory) {\n // Ensure the given history is not empty\n require(self.length != 0, \"L5\");\n\n // Retrieve latest pack's index and cursor\n uint256 packIndex = self.length - 1;\n uint32 packCursor = self[packIndex].cursor;\n\n // If this is the first pack ever, ensure it is not empty\n if (packIndex == 0) require(packCursor != 0, \"L6\");\n\n // If the pack is empty, return ref of previous pack's latest slot\n if (packCursor == 0) return Reference(packIndex - 1, 3);\n //\n // Else, return ref of previous slot in current pack\n else return Reference(packIndex, packCursor - 1);\n }\n\n /**\n * @notice Appends a new empty pack to the end of the given APR history array.\n * @param self The APR history to append an empty to.\n */\n function newBlankPack(Pack[] storage self) internal {\n // If history is not empty, ensure the latest pack is full\n require(self.length == 0 || getLatestReference(self).cursorIndex == 3, \"L7\");\n\n // Push a new blank pack to the history array\n self.push(\n Pack({\n aprsUD7x3: [uint16(0), uint16(0), uint16(0), uint16(0)],\n timestamps: [uint40(0), uint40(0), uint40(0), uint40(0)],\n cursor: 0\n })\n );\n }\n\n /**\n * @notice Write a new APR checkpoint at the end of the given history array.\n * @param self The array of packs to write the new checkpoint to.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(Pack[] storage self, uint16 aprUD7x3) external {\n // Determine the reference where the new checkpoint should be written\n Reference memory newRef = self.length == 0\n ? Reference(0, 0)\n : incrementReference(getLatestReference(self));\n\n // If pack to be written doesn't exist yet, push a new blank pack in history\n if (newRef.packIndex >= self.length) newBlankPack(self);\n\n // Retrieve the pack where the new checkpoint will be stored\n Pack memory pack = self[newRef.packIndex];\n\n // Add new checkpoint's data to the pack\n pack.aprsUD7x3[newRef.cursorIndex] = aprUD7x3;\n pack.timestamps[newRef.cursorIndex] = uint40(block.timestamp);\n\n // Increment the pack's cursor\n pack.cursor++;\n\n // Write the updated pack in storage\n self[newRef.packIndex] = pack;\n }\n\n /**\n * @notice Retrieves the APR of the latest checkpoint written in the APR history.\n * @param self The history array to read APR from.\n * @return The latest checkpoint's APR.\n */\n function getAPR(Pack[] storage self) public view returns (uint16) {\n // Retrieve the latest checkpoint data\n Reference memory ref = getLatestReference(self);\n CheckpointData memory data = getDataFromReference(self, ref);\n\n // Return the latest checkpoint's APR\n return data.aprUD7x3;\n }\n}\n" + }, + "contracts/src/libs/SUD.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title SUD\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice SUD serves as an intermediary number format for calculations within this\n * codebase. It ensures consistency and reduces precision losses. This library\n * facilitates conversions between various number formats and the SUD format.\n *\n * @dev Intuition:\n * This codebase employs the UD (unsigned decimal fixed-point numbers) format to\n * represent both percentage rates and tokens amounts.\n *\n * Rates are expressed in UD7x3 format, whereas the format for tokens amounts depends on\n * the decimals() value of the involved tokens.\n *\n * Three challenges arise from this:\n * 1) To compute values together, it's essential that they are in the same format\n * 2) Calculations involving consecutive divisions on UD numbers lead to accumulated\n * precision loss (because division shrinks). A common approach is to scale up and\n * down values by a few decimals before and after performing calculations.\n * 3) Given that rates use the UD7x3 format, if we decided to scale them to and from\n * the number of decimals of the involved token, 1 to 3 of the rates' decimals would\n * be shrunk in case token's decimals number is in [0, 2].\n *\n * To address these challenges, this library provides the SUD format, which acts as a\n * consistent and scaled intermediate format to perform calculations.\n *\n * SUD is an acronym for either \"Scaled UD\" or \"Safe UD\".\n *\n * @dev Definitions:\n * - Integer: A number without fractional part, e.g., block.timestamp\n * - UD: A decimal unsigned fixed-point number. The \"UD\" notation is inspired from\n * libraries like [prb-math](https://github.com/PaulRBerg/prb-math/)\n * - Amount: A token amount. A UD with an unknown repartition of digits between integral\n * and fractional parts (as token amounts have variable decimal numbers)\n * - Rate: A percentage rate. An UD with 7 integral digits and 3 fractional ones (= UD7x3)\n * - SUD: An intermediate format to perform calculations involving Rates and Amounts. A UD\n * with 3 more decimals than the involved UD with the highest decimals number. As\n * rates are represented by UD7x3, a SUD number has at least 6 decimals (3+3) and\n * so ranges from UD71x6 to UD0x77 formats.\n *\n * @dev A conversion library:\n * This library provides utilities to perform the following conversions:\n * - Amount <--> SUD\n * - Rate (UD7x3) <--> SUD\n * - Integer <--> SUD\n *\n * @dev Why scaling by 3 decimals?\n * - It provides an adequate degree of precision for this codebase,\n * - It enables the conversion of a UD7x3 rate to SUD format by merely scaling it up by\n * the involved token's decimal number, so is gas efficient.\n *\n * @dev Why internal functions?\n * The functions of this library are not set to external because incorporating them\n * directly into contracts is more gas-efficient. Given their minimal size and frequent\n * usage in the InvestUpgradeable, LDYStaking, and LToken contracts, any bytecode savings\n * from making them external are negated by the additional bytecode required for external\n * calls to this library. This can be observed by comparing the output of `bun cc:size`\n * when those functions's visibility is set to external or internal.\n *\n * @dev Precision warning:\n * While this library mitigates precision loss during calculations on UD numbers, it's\n * important to note that tokens with lower decimal counts and supply inherently suffer\n * more from precision loss. Conversely, tokens with higher decimal counts and supply\n * will experience less precision loss.\n *\n * @dev For further details, see \"SUD\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary SUD {\n /**\n * @notice Retrieves decimals number of the given ERC20 contract address.\n * @param tokenAddress The address to retrieve decimals number from.\n * @return decimals The decimals number of the given ERC20 contract address.\n */\n function decimalsOf(address tokenAddress) internal view returns (uint256 decimals) {\n return IERC20MetadataUpgradeable(tokenAddress).decimals();\n }\n\n /**\n * @notice Convert a given token amount into SUD format.\n * @param nAmount The token amount to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The amount in SUD format\n */\n function fromAmount(uint256 nAmount, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nAmount * 10 ** (6 - decimals);\n\n // Else return a number with decimals+3 fractional digits\n return nAmount * 10 ** 3;\n }\n\n /**\n * @notice Convert a given SUD number into token amount format.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nAmount The number in amount format\n */\n function toAmount(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nAmount) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** (6 - decimals);\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** 3;\n }\n\n /**\n * @notice Converts a given UD7x3 rate into SUD format.\n * @param nUD7x3 The UD7x3 rate to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The rate in SUD format.\n */\n function fromRate(uint256 nUD7x3, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nUD7x3 * 10 ** 3;\n\n // Else, return a number with decimals+3 fractional digits\n return nUD7x3 * 10 ** decimals;\n }\n\n /**\n * @notice Converts a given SUD number into a UD7x3 rate.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nUD7x3 The number in UD7x3 rate format.\n */\n function toRate(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nUD7x3) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 3;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** decimals;\n }\n\n /**\n * @notice Converts a given integer into SUD format.\n * @param n The integer to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The integer in SUD format.\n */\n function fromInt(uint256 n, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return n * 10 ** 6;\n\n // Else, return a number with decimals+3 fractional digits\n return n * 10 ** (decimals + 3);\n }\n\n /**\n * @notice Converts a given SUD number as an integer (all decimals shrinked).\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return n The SUD number as an integer.\n */\n function toInt(uint256 nSUD, uint256 decimals) internal pure returns (uint256 n) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 6;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** (decimals + 3);\n }\n}\n" + }, + "contracts/src/LToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ERC20WrapperUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\";\nimport \"./abstracts/base/ERC20BaseUpgradeable.sol\";\nimport {InvestUpgradeable} from \"./abstracts/InvestUpgradeable.sol\";\nimport {LDYStaking} from \"./LDYStaking.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {SUD} from \"./libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {ITransfersListener} from \"./interfaces/ITransfersListener.sol\";\n\n/**\n * @title LToken\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e.,\n * investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin.\n * As soon as a wallet holds some L-Tokens, it starts receiving rewards in\n * the form of additional L-Tokens, which are auto-compounded over time.\n *\n * @dev Definitions:\n * - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio).\n * - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees).\n * - Instant: Processed immediately.\n * - Request: Queued for later processing.\n * - Big Request: A requested withdrawal exceeding half of the retention rate.\n * - (Withdrawal) queue: A list of all requested withdrawals sorted by priority.\n * - Request ID: The index of a withdrawal request in the queue array.\n * - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain.\n * - Fees Rate: Percentage of fees applied to successful withdrawals.\n * - Usable underlyings: Amount of underlying tokens that have been deposited through\n * expected ways and are so considered safe to use by the contract.\n * - Transfers listeners: External contracts listening on L-Tokens transfers.\n * - Fund wallet: Wallet managed by the Ledgity's financial team.\n * - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request\n * processing.\n *\n * Note that words between parenthesis are sometimes omitted for brevity.\n *\n * @dev Deployment notice:\n * This contract can safely receive funds immediately after initialization. (i.e., there\n * is no way for funds to be sent to non-owned addresses). It is, however, recommended to\n * replace ASAP owner and fund wallets with multi-sig wallets.\n *\n * @dev For further details, see \"LToken\" section of whitepaper.\n * @custom:oz-upgrades-unsafe-allow external-library-linking\n * @custom:security-contact security@ledgity.com\n */\ncontract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @dev Represents type of actions triggering ActivityEvent events.\n enum Action {\n Deposit,\n Withdraw\n }\n\n /// @dev Represents different status of actions triggering ActivityEvent events.\n enum Status {\n Queued,\n Cancelled,\n Success,\n Moved\n }\n\n /**\n * @notice Represents a withdrawal request in the queue.\n * @dev A request fits in a single storage slot (32 bytes).\n * @param account The account that initiated the request.\n * @param amount The amount of underlying tokens requested.\n */\n struct WithdrawalRequest {\n address account; // 20 bytes\n uint96 amount; // 12 bytes\n }\n\n /// @notice Upper limit of retention rate.\n uint32 private constant MAX_RETENTION_RATE_UD7x3 = 10 * 10 ** 3; // 10%\n\n /// @notice Upper limit of fees rate.\n uint32 private constant MAX_FEES_RATE_UD7x3 = 20 * 10 ** 3; // 20%\n\n /// @notice Used in activity events to represent the absence of request ID.\n int256 private constant NO_ID = -1;\n\n /// @notice Holds a reference to the LDYStaking contract.\n LDYStaking public ldyStaking;\n\n /// @notice Holds address of withdrawer wallet (managed by withdrawal server).\n address payable public withdrawer;\n\n /// @notice Holds address of fund wallet (managed by Ledgity financial team).\n address public fund;\n\n /// @notice Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\n uint32 public feesRateUD7x3;\n\n /// @notice Holds the retention rate in UD7x3 format.\n uint32 public retentionRateUD7x3;\n\n /// @notice Holds the amount of withdrawal fees not yet claimed by contract's owner.\n uint256 public unclaimedFees;\n\n /// @notice Holds the amount of L-Tokens currently in the withdrawal queue.\n uint256 public totalQueued;\n\n /**\n * @notice Holds the amount of underlying tokens considered as usable by the contract.\n * @dev Are usable, only underlying tokens deposit through deposit() or fund() functions.\n */\n uint256 public usableUnderlyings;\n\n /// @notice Holds an ordered list of active withdrawal requests.\n WithdrawalRequest[] public withdrawalQueue;\n\n /// @notice Holds the index of the next withdrawal request to process in the queue.\n uint256 public withdrawalQueueCursor;\n\n /**\n * @notice Holds a list of all currently frozen withdrawal requests.\n * @dev If a request emitter as been blacklisted, its request is moved here to prevent\n * it from blocking the queue.\n */\n WithdrawalRequest[] public frozenRequests;\n\n /**\n * @notice Holds a list of contracts' references that are listening to L-Tokens transfers.\n * @dev onLTokenTransfer() functions of those contracts will be called on each transfer.\n */\n ITransfersListener[] public transfersListeners;\n\n /**\n * @notice Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet.\n */\n uint256 public withdrwalFeeInEth;\n\n /**\n * @notice Emitted to inform listeners about a change in the contract's TVL.\n * @dev TVL = realTotalSupply()\n * @param newTVL The new TVL of the contract.\n */\n event TVLChangeEvent(uint256 newTVL);\n\n /**\n * @notice Emitted to inform listerners about an activity related to deposits and withdrawals.\n * @param id ID of the involved withdrawal request or NO_ID (-1) if not applicable.\n * @param account The account involved in the activity.\n * @param action The type of activity.\n * @param amount The amount of underlying tokens involved in the activity.\n * @param newStatus The new status of the activity.\n * @param newId The new ID of the request if it has been moved in the queue.\n */\n event ActivityEvent(\n int256 indexed id,\n address indexed account,\n Action indexed action,\n uint256 amount,\n uint256 amountAfterFees,\n Status newStatus,\n int256 newId\n );\n\n /**\n * @notice Emitted to inform listeners that some rewards have been minted.\n * @param account The account that received the rewards.\n * @param balanceBefore The balance of the account before the minting.\n * @param rewards The amount of minted rewards.\n */\n event MintedRewardsEvent(address indexed account, uint256 balanceBefore, uint256 rewards);\n\n /// @notice Reverts if the function caller is not the withdrawer wallet.\n modifier onlyWithdrawer() {\n require(_msgSender() == withdrawer, \"L39\");\n _;\n }\n\n /// @notice Reverts if the function caller is not the fund wallet.\n modifier onlyFund() {\n require(_msgSender() == fund, \"L40\");\n _;\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param underlyingToken The address of the underlying stablecoin ERC20 token.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address ldyStaking_,\n address underlyingToken\n ) public initializer {\n // Initialize ERC20 base.\n string memory underlyingSymbol = IERC20MetadataUpgradeable(underlyingToken).symbol();\n __ERC20Base_init(\n globalOwner_,\n globalPause_,\n globalBlacklist_,\n string(abi.encodePacked(\"Ledgity \", underlyingSymbol)),\n string(abi.encodePacked(\"L\", underlyingSymbol))\n );\n\n // IMPORTANT: Below calls must not be restricted to owner at any point.\n // This is because the GlobalOwner contract may not be a fresh one, and so\n // the contract deployer may not be the owner anymore after ERC20Base init.\n\n // Initialize other parents contracts.\n __ERC20Wrapper_init(IERC20Upgradeable(underlyingToken));\n __Invest_init_unchained(address(this));\n\n // Set LDYStaking contract\n ldyStaking = LDYStaking(ldyStaking_);\n\n // Set initial withdrawal fees rate to 0.3%\n feesRateUD7x3 = 300;\n\n // Set initial retention rate to 10%\n retentionRateUD7x3 = 10_000;\n\n // Default withdrawer and fund wallet to contract owner address. This prevents\n // any loss of funds if a deposit/withdrawal is made before those are manually set.\n withdrawer = payable(owner());\n fund = payable(owner());\n\n // Set initial withdrwalFeeInEth\n withdrwalFeeInEth = 0.003 * 1e18;\n }\n\n /**\n * @notice Required override of decimals() which is implemented by both\n * ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\n * @dev The ERC20WrapperUpgradeable version is preferred because it mirrors the\n * decimals amount of the underlying stablecoin token.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function decimals()\n public\n view\n override(ERC20Upgradeable, ERC20WrapperUpgradeable)\n returns (uint8)\n {\n return ERC20WrapperUpgradeable.decimals();\n }\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\n * @dev Both version are the same as ERC20BaseUpgradeable.paused() mirrors\n * GlobalPausableUpgradeable.paused(), so a random one is chosen.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, ERC20BaseUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @notice Updates the current withdrawal fee rate.\n * @param feesRateUD7x3_ The new withdrawal fee rate in UD7x3 format.\n */\n function setFeesRate(uint32 feesRateUD7x3_) public onlyOwner {\n require(feesRateUD7x3_ <= MAX_FEES_RATE_UD7x3, \"L88\");\n feesRateUD7x3 = feesRateUD7x3_;\n }\n\n /**\n * @notice Updates the current withdrawalFeeInETH.\n * @param withdrwalFeeInEth_ The new withdrawalFee in ETH.\n */\n function setWithdrwalFeeInEth(uint32 withdrwalFeeInEth_) public onlyOwner {\n require(withdrwalFeeInEth <= MAX_FEES_RATE_UD7x3, \"L88\");\n withdrwalFeeInEth = withdrwalFeeInEth_;\n }\n\n /**\n * @notice Updates the current underlying token retention rate.\n * @dev The retention rate is capped at 10%, which ensures that no more than 10% of\n * deposited assets will ever be exposed in this contract (reduces attack surface).\n * @param retentionRateUD7x3_ The new retention rate in UD7x3 format.\n */\n function setRetentionRate(uint32 retentionRateUD7x3_) public onlyOwner {\n require(retentionRateUD7x3_ <= MAX_RETENTION_RATE_UD7x3, \"L41\");\n retentionRateUD7x3 = retentionRateUD7x3_;\n }\n\n /**\n * @notice Updates the address of LDYStaking contract.\n * @param ldyStakingAddress The address of the new LDYStaking contract.\n */\n function setLDYStaking(address ldyStakingAddress) public onlyOwner {\n ldyStaking = LDYStaking(ldyStakingAddress);\n }\n\n /**\n * @notice Updates the address of the withdrawer wallet.\n * @param withdrawer_ The address of the new withdrawer wallet.\n */\n function setWithdrawer(address payable withdrawer_) public onlyOwner {\n // Ensure address is not the zero address (pre-processing fees would be lost else)\n require(withdrawer_ != address(0), \"L63\");\n\n // Set new withdrawer wallet's address\n withdrawer = withdrawer_;\n }\n\n /**\n * @notice Updates the address of the fund wallet.\n * @param fund_ The address of the new fund wallet.\n */\n function setFund(address payable fund_) public onlyOwner {\n // Ensure address is not the zero address (deposited tokens would be lost else)\n require(fund_ != address(0), \"L64\");\n\n // Set new fund wallet's address\n fund = fund_;\n }\n\n /**\n * @notice Adds a new contract to the L-Token transfers list.\n * @dev Each time a transfer occurs, the onLTokenTransfer() function of the\n * specified contract will be called.\n * @dev IMPORTANT SECURITY NOTE: This method is not intended to be used with\n * contracts that are not owned by the Ledgity team.\n * @param listenerContract The address of the new transfers listener contract.\n */\n function listenToTransfers(address listenerContract) public onlyOwner {\n transfersListeners.push(ITransfersListener(listenerContract));\n }\n\n /**\n * @notice Removes a contract from the L-Token transfers list.\n * @dev The onLTokenTransfer() function of the specified contract will not be called\n * anymore each time a L-Token transfer occurs.\n * @param listenerContract The address of the listener contract.\n */\n function unlistenToTransfers(address listenerContract) public onlyOwner {\n // Find index of listener contract in transferListeners array\n int256 index = -1;\n uint256 transfersListenersLength = transfersListeners.length;\n for (uint256 i = 0; i < transfersListenersLength; i++) {\n if (address(transfersListeners[i]) == listenerContract) {\n index = int256(i);\n break;\n }\n }\n\n // Revert if given contract wasn't listening to transfers\n require(index > -1, \"L42\");\n\n // Else, remove transfers listener contract from listeners array\n transfersListeners[uint256(index)] = transfersListeners[transfersListenersLength - 1];\n transfersListeners.pop();\n }\n\n /**\n * @notice Retrieves the amount of given account's not yet minted rewards.\n * @dev This is a public implementation of InvestUpgradeable_rewardsOf(). In the\n * context of LToken, this function returns the amount of rewards that have not been\n * distributed/minted yet to the specified account.\n * @dev This is particularly useful for off-chain services to display charts and\n * statistics, as seen in the Ledgity Yield's frontend.\n * @param account The account to check the unminted rewards of.\n * @return The amount of account's unminted rewards.\n */\n function unmintedRewardsOf(address account) public view returns (uint256) {\n return _rewardsOf(account, true);\n }\n\n /**\n * @notice Retrieves the \"real\" balance of an account, i.e., excluding its not yet\n * minted/distributed rewards.\n * @param account The account to check the real balance of.\n * @return The real balance of the account.\n */\n function realBalanceOf(address account) public view returns (uint256) {\n return super.balanceOf(account);\n }\n\n /**\n * @notice Retrieves the total balance of L-Tokens that belong to the account.\n * @dev This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have\n * not been yet minted to the specified account.\n * @param account The account to check the total balance of.\n * @return The total balance of the account.\n */\n function balanceOf(address account) public view override returns (uint256) {\n return realBalanceOf(account) + unmintedRewardsOf(account);\n }\n\n /**\n * @notice Returns the \"real\" amount of existing L-Tokens, i.e., excluding not yet\n * minted withdrawal fees and L-Tokens currently in the withdrawal queue.\n * @return The real total supply of L-Tokens.\n */\n function realTotalSupply() public view returns (uint256) {\n return super.totalSupply();\n }\n\n /**\n * @notice Retrives the total supply of L-Tokens, including not yet minted withdrawal\n * fees and L-Tokens currently in the withdrawal queue.\n * @return The total supply of L-Tokens.\n */\n function totalSupply() public view override returns (uint256) {\n return realTotalSupply() + totalQueued + unclaimedFees;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address.\n * @dev This override of RecoverableUpgradeable.recoverERC20() prevents the recovered\n * token from being the underlying token.\n * @inheritdoc RecoverableUpgradeable\n */\n function recoverERC20(address tokenAddress, uint256 amount) public override onlyOwner {\n // Ensure the token is not the underlying token\n require(tokenAddress != address(underlying()), \"L43\");\n\n // Proceed to recovery\n super.recoverERC20(tokenAddress, amount);\n }\n\n /**\n * @notice Recovers underlying tokens accidentally sent to the contract.\n * @dev To prevent owner from being able to drain the contract, this function only\n * allows recovering \"unusable\" underlying tokens, i.e., tokens that have not been\n * sent through fund() or deposit() functions.\n */\n function recoverUnderlying() external onlyOwner {\n // Compute the recoverable amount by taking the difference between the contract's\n // balance and the amount of usable underlying tokens\n uint256 recoverableAmount = underlying().balanceOf(address(this)) - usableUnderlyings;\n\n // Revert if there is nothing to recover\n require(recoverableAmount > 0, \"L44\");\n\n // Else, proceed to underlying tokens recovery\n super.recoverERC20(address(underlying()), recoverableAmount);\n }\n\n /**\n * @notice Retrieves the amount of underlying tokens invested by the given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract. In\n * LToken contract, the investment of an account is equal to its real balance.\n * @inheritdoc InvestUpgradeable\n */\n function _investmentOf(address account) internal view override returns (uint256) {\n return realBalanceOf(account);\n }\n\n /**\n * @notice Distributes a specified amount of rewards (in L-Tokens) to a given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract so\n * it can distribute rewards to accounts before each period reset.\n * @dev InvestUpgradeable contract already ensure that amount > 0.\n * @inheritdoc InvestUpgradeable\n */\n function _distributeRewards(address account, uint256 amount) internal override returns (bool) {\n // Inform listeners of the rewards minting\n emit MintedRewardsEvent(account, realBalanceOf(account), amount);\n\n // Mint L-Tokens rewards to account\n _mint(account, amount);\n\n // Return true indicating to InvestUpgradeable that the rewards have been distributed\n return true;\n }\n\n /**\n * @notice Override of ERC20._beforeTokenTransfer() to integrate with InvestUpgradeable.\n * @dev This overriden version ensure that _beforeInvestmentChange() hook is properly\n * called each time an account's balance is going to change.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already included in ERC20BaseUpgradeable._beforeTokenTransfer().\n * @inheritdoc ERC20BaseUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20Upgradeable, ERC20BaseUpgradeable) {\n ERC20BaseUpgradeable._beforeTokenTransfer(from, to, amount);\n\n // Invoke _beforeInvestmentChange() hook for non-zero accounts\n if (from != address(0)) _beforeInvestmentChange(from, true);\n if (to != address(0)) _beforeInvestmentChange(to, true);\n }\n\n /**\n * @notice Override of ERC20._afterTokenTransfer() to notify all transfers listeners.\n * @dev This overriden version will trigger onLTokenTransfer() functions of all\n * transfers listeners.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already checked in _beforeTokenTransfer().\n * @inheritdoc ERC20Upgradeable\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\n super._afterTokenTransfer(from, to, amount);\n\n // If some L-Token have been burned/minted, inform listeners of a TVL change\n if (from == address(0) || to == address(0)) emit TVLChangeEvent(totalSupply());\n\n // Trigger onLTokenTransfer() functions of all the transfers listeners\n for (uint256 i = 0; i < transfersListeners.length; i++) {\n transfersListeners[i].onLTokenTransfer(from, to, amount);\n }\n }\n\n /**\n * @notice Computes the maximum amount of underlying tokens that should be retained\n * by the contract (based on retention rate).\n * @return amount The expected amount of retained underlying tokens.\n */\n function getExpectedRetained() public view returns (uint256 amount) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert totalSupply and retentionRate to SUD\n uint256 totalSupplySUD = SUD.fromAmount(totalSupply(), d);\n uint256 retentionRateSUD = SUD.fromRate(retentionRateUD7x3, d);\n\n // Compute and return expected retained amount\n uint256 expectedRetainedSUD = (totalSupplySUD * retentionRateSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(expectedRetainedSUD, d);\n }\n\n /// @notice Transfers underlying tokens exceeding the retention rate to the fund wallet.\n function _transferExceedingToFund() internal {\n // Retrieve the expected amount retained\n uint256 expectedRetained = getExpectedRetained();\n\n // If usable underlyings are less than or equal to expected retained, return\n if (usableUnderlyings <= expectedRetained) return;\n\n // Else, exceeding amount is equal to difference between those values\n uint256 exceedingAmount = usableUnderlyings - expectedRetained;\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= exceedingAmount;\n\n // Transfer the exceeding amount to the fund wallet\n underlying().safeTransfer(fund, exceedingAmount);\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.withdrawTo() that reverts.\n * Use instantWithdrawal() or requestWithdrawal() functions instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function withdrawTo(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L45\");\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.depositFor() that reverts.\n * Use deposit() function instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function depositFor(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L46\");\n }\n\n /**\n * @notice Allows exchanging some underlying tokens for the same amount of L-Tokens.\n * @param amount The amount of underlying tokens to deposit.\n */\n function deposit(uint256 amount) public whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough underlying tokens to deposit\n require(underlying().balanceOf(_msgSender()) >= amount, \"L47\");\n\n // Update usable underlyings balance accordingly\n usableUnderlyings += amount;\n\n // Inform listeners of the deposit activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Deposit,\n amount,\n amount,\n Status.Success,\n NO_ID\n );\n\n // Receive underlying tokens and mint L-Tokens to the account in a 1:1 ratio\n super.depositFor(_msgSender(), amount);\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Computes fees and net withdrawn amount for a given account withdrawing a\n * given amount.\n * @param account The account initiating the withdrawal.\n * @param amount The amount of the withdrawal.\n */\n function getWithdrawnAmountAndFees(\n address account,\n uint256 amount\n ) public view returns (uint256 withdrawnAmount, uint256 fees) {\n // If the account is eligible to staking tier 2, no fees are applied\n if (ldyStaking.tierOf(account) >= 2) return (amount, 0);\n\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert amount and fees rate to SUD\n uint256 amountSUD = SUD.fromAmount(amount, d);\n uint256 feesRateSUD = SUD.fromRate(feesRateUD7x3, d);\n\n // Compute fees and withdrawn amount (initial amount minus fees)\n uint256 feesSUD = (amountSUD * feesRateSUD) / SUD.fromInt(100, d);\n fees = SUD.toAmount(feesSUD, d);\n withdrawnAmount = amount - fees;\n }\n\n /**\n * @notice Allows instaneously exchanging a given amount of L-Tokens for the same\n * amount of underlying tokens. It will fail if the contract currently doesn't hold\n * enough underlying tokens to cover the withdrawal.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestWithdrawal() function otherwise.\n * @param amount The amount L-Tokens to withdraw.\n */\n function instantWithdrawal(uint256 amount) external whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L48\");\n\n // Can the contract cover this withdrawal plus all already queued requests?\n bool cond1 = totalQueued + amount <= usableUnderlyings;\n\n // Is caller eligible to staking tier 2 and the contract can cover this withdrawal?\n bool cond2 = ldyStaking.tierOf(_msgSender()) >= 2 && amount <= usableUnderlyings;\n\n // Revert if conditions are not met for the withdrawal to be processed instantaneously\n if (!(cond1 || cond2)) revert(\"L49\");\n\n // Else, retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(_msgSender(), amount);\n\n // Increase unclaimed fees amount accordingly\n unclaimedFees += fees;\n\n // Decrease usable underlyings balance accordingly\n usableUnderlyings -= withdrawnAmount;\n\n // Inform listeners of this instant withdrawal activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Withdraw,\n amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Burn withdrawal fees from the account\n _burn(_msgSender(), fees);\n\n // Burn account's withdrawn L-Tokens and transfer to it underlying tokens in a 1:1 ratio\n super.withdrawTo(_msgSender(), withdrawnAmount);\n }\n\n /**\n * @notice Allows requesting the exchange of a given amount of L-Tokens for the same\n * amount of underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n * @param amount The amount L-Tokens to withdraw.\n */\n function requestWithdrawal(\n uint256 amount\n ) public payable whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L53\");\n\n // Ensure the requested amount doesn't overflow uint96\n require(amount <= type(uint96).max, \"L54\");\n\n // Ensure the sender attached the pre-paid processing gas fees\n require(msg.value == withdrwalFeeInEth, \"L55\");\n\n // Create withdrawal request data\n WithdrawalRequest memory request = WithdrawalRequest({\n account: _msgSender(),\n amount: uint96(amount)\n });\n\n // Will hold the request ID\n uint256 requestId;\n\n // Append request to the withdrawal queue:\n // - At the beginning, if account is eligible to staking tier 2 and cursor is not 0\n if (ldyStaking.tierOf(_msgSender()) >= 2 && withdrawalQueueCursor > 0) {\n withdrawalQueueCursor--;\n requestId = withdrawalQueueCursor;\n withdrawalQueue[requestId] = request;\n }\n // - At the end else\n else {\n withdrawalQueue.push(request);\n requestId = withdrawalQueue.length - 1;\n }\n\n // Increase total amount queued accordingly\n totalQueued += amount;\n\n // Inform listeners of this new queued withdrawal activity event\n emit ActivityEvent(\n int256(requestId),\n _msgSender(),\n Action.Withdraw,\n amount,\n amount,\n Status.Queued,\n NO_ID\n );\n\n // Burn withdrawal L-Tokens amount from account's balance\n _burn(_msgSender(), amount);\n\n // Forward pre-paid processing gas fees to the withdrawer wallet\n (bool sent, ) = withdrawer.call{value: msg.value}(\"\");\n require(sent, \"L56\");\n }\n\n /**\n * @notice Processes queued withdrawal requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n * @dev For further details, see \"LToken > Withdrawals\" section of whitepaper.\n */\n function processQueuedRequests() external onlyWithdrawer whenNotPaused {\n // Accumulators variables, will be written on-chain after the loop\n uint256 cumulatedFees = 0;\n uint256 cumulatedWithdrawnAmount = 0;\n uint256 nextRequestId = withdrawalQueueCursor;\n\n // Cache queue length to avoid multiple SLOADs and avoid infinite loop as big\n // requests are increasing the queue length when moved at the end of the queue.\n uint256 queueLength = withdrawalQueue.length;\n\n // Iterate over requests to be processed\n while (nextRequestId < queueLength) {\n // Stop processing requests if there is not enough gas left to continue the\n // loop and properly end the function call. This prevents an attacker from\n // blocking the withdrawal processing by creating a ton of tiny requests so\n // this function call cannot fit anymore in block gas limit.\n if (gasleft() < 45000) break;\n\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[nextRequestId];\n\n // Skip empty request (processed big requests or cancelled requests)\n if (request.account == address(0)) {}\n //\n // If account has been blacklisted since request emission\n else if (isBlacklisted(request.account)) {\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request in the frozen requests list\n frozenRequests.push(request);\n }\n //\n // Or if request is a big request, move it at the end of the queue for now.\n // This request will be processed manually later using processBigQueuedRequest()\n else if (request.amount > getExpectedRetained() / 2) {\n // Inform listeners of this queued request being moved at the end of the queue\n emit ActivityEvent(\n int256(nextRequestId),\n _msgSender(),\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Moved,\n int256(withdrawalQueue.length)\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request at the end of the queue\n withdrawalQueue.push(request);\n }\n //\n // Else, continue request processing\n else {\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Break if the contract doesn't hold enough funds to cover the request\n if (withdrawnAmount > usableUnderlyings - cumulatedWithdrawnAmount) break;\n\n // Accumulate fees and withdrawn amount\n cumulatedFees += fees;\n cumulatedWithdrawnAmount += withdrawnAmount;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(nextRequestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Transfer underlying tokens to account. Burning L-Tokens is not required\n // as equestWithdrawal() already did it.\n // Security note: Re-entrancy warning are disabled as the request has\n // just been deleted from the queue, it will so be skipped if trying to\n // process it again.\n // slither-disable-next-line reentrancy-no-eth\n underlying().safeTransfer(request.account, withdrawnAmount);\n }\n\n // Increment next request ID\n nextRequestId++;\n }\n\n // Increase unclaimed fees by the amount of cumulated fees\n unclaimedFees += cumulatedFees;\n\n // Decrease usable underlyings by the cumulated amount of withdrawn underlyings\n usableUnderlyings -= cumulatedWithdrawnAmount;\n\n // Decrease total amount queued by the cumulated amount requested\n totalQueued -= cumulatedWithdrawnAmount + cumulatedFees;\n\n // Update new queue cursor\n withdrawalQueueCursor = nextRequestId;\n\n // Retention rate cannot exceeds as the withdrawal decreases both usable\n // underlyings and expected retained amounts by the same number and as the\n // expected retained amount is a subset of usable underlyings amount.\n }\n\n /**\n * @notice Processes a given queued big withdrawal request (one that exceeds half of\n * the retention rate).\n * @dev In contrast to non-big requests processing, this function will uses to fund\n * wallet's balance to fill the request. This allows processing requests that are\n * greater than retention rate without having to exceed this rate on the contract.\n * @param requestId The ID of the big request to process.\n */\n function processBigQueuedRequest(uint256 requestId) external onlyFund whenNotPaused {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure the request is active\n require(request.account != address(0), \"L66\");\n\n // Ensure the request emitter has not been blacklisted since request emission\n require(!isBlacklisted(request.account), \"L50\");\n\n // Ensure this is indeed a big request\n require(request.amount > getExpectedRetained() / 2, \"L51\");\n\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Ensure withdrawn amount can be covered by contract + fund wallet balances\n uint256 fundBalance = underlying().balanceOf(fund);\n require(withdrawnAmount <= usableUnderlyings + fundBalance, \"L52\");\n\n // Increase amount of unclaimed fees accordingly\n unclaimedFees += fees;\n\n // Decrease total queued amount by request amount\n totalQueued -= request.amount;\n\n // Increment queue cursor if request was the next request to be processed\n if (requestId == withdrawalQueueCursor) withdrawalQueueCursor++;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[requestId];\n\n // If fund wallet's balance can cover request, rely on it only\n if (withdrawnAmount <= fundBalance) {\n underlying().safeTransferFrom(_msgSender(), request.account, withdrawnAmount);\n }\n // Else, cover request from both fund wallet and contract balances\n else {\n // Compute amount missing from fund wallet to cover request\n uint256 missingAmount = withdrawnAmount - fundBalance;\n\n // Decrease usable amount of underlying tokens accordingly\n usableUnderlyings -= missingAmount;\n\n // Transfer entire fund balance to request's emitter\n underlying().safeTransferFrom(_msgSender(), request.account, fundBalance);\n\n // Transfer missing amount from contract balance to request emitter\n underlying().safeTransfer(request.account, missingAmount);\n }\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Cancels a given withdrawal request. The request emitter receive back its\n * L-Tokens and no fees will be charged.\n * @param requestId The ID of the withdrawal request to cancel.\n */\n function cancelWithdrawalRequest(\n uint256 requestId\n ) public whenNotPaused notBlacklisted(_msgSender()) {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure request belongs to caller\n require(_msgSender() == request.account, \"L57\");\n\n // Decrease total amount queued accordingly\n totalQueued -= request.amount;\n\n // Delete the withdrawal request from queue\n delete withdrawalQueue[requestId];\n\n // Inform listeners of this cancelled withdrawal request activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Cancelled,\n NO_ID\n );\n\n // Mint back L-Tokens to account\n _mint(request.account, uint256(request.amount));\n }\n\n /**\n * @notice Used by the fund wallet to repatriate underlying tokens on the contract\n * whenever those are required to fulfill some withdrawal requests.\n * @dev The function will revert if repatriated amount makes the contract exceeding\n * the retention rate.\n * @param amount The amount of underlying tokens to repatriate.\n */\n function repatriate(uint256 amount) external onlyFund whenNotPaused {\n // Ensure the fund wallet has enough funds to repatriate\n require(amount <= underlying().balanceOf(fund), \"L58\");\n\n // Calculate new contract usable balance\n uint256 newBalance = usableUnderlyings + amount;\n\n // Ensure the new balance doesn't exceed the retention rate\n require(newBalance <= getExpectedRetained(), \"L59\");\n\n // Increase usable underlyings amount by repatriated amount\n usableUnderlyings += amount;\n\n // Transfer amount from fund wallet to contract\n underlying().safeTransferFrom(_msgSender(), address(this), amount);\n }\n\n /// @notice Used by owner to claim fees generated from successful withdrawals.\n function claimFees() external onlyOwner {\n // Ensure there are some fees to claim\n require(unclaimedFees > 0, \"L60\");\n\n // Ensure the contract holds enough underlying tokens to cover fees\n require(usableUnderlyings >= unclaimedFees, \"L61\");\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= unclaimedFees;\n\n // Store fees amount in memory and reset unclaimed fees amount\n uint256 fees = unclaimedFees;\n unclaimedFees = 0;\n\n // Transfer unclaimed fees to owner\n underlying().safeTransfer(owner(), fees);\n }\n}\n" + }, + "contracts/src/LTokenSignaler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title LTokenSignaler\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Used to inform subgraph from the existence of a new L-Token contract. Once\n * signaled, a L-Token will start being indexed.\n *\n * @dev Signal are ignored by the subgraph if the L-Token is already known by it.\n *\n * @custom:security-contact security@ledgity.com\n */\ncontract LTokenSignaler is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\n /**\n * @notice Emitted to inform subgraph of the existence of a new L-Token contract.\n * @param lTokenAddress The address of the L-Token contract to signal.\n */\n event LTokenSignalEvent(address indexed lTokenAddress);\n\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @notice Signals a LToken contract to the TheGraph subgraph of the current chain.\n * @param lTokenAddress The address of the LToken contract to signal.\n */\n function signalLToken(address lTokenAddress) external onlyOwner {\n // Signal the LToken contract\n emit LTokenSignalEvent(lTokenAddress);\n }\n}\n" + }, + "contracts/src/PreMining.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {LToken} from \"./LToken.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {Pausable} from \"@openzeppelin/contracts/security/Pausable.sol\";\n\n/**\n * @title PreMining\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n\n * @notice PreMining pool contract, allowing accounts to lock underlying tokens in a \n * pre-defined L-Token contract, over a given duration (in months), in exchange of \n * vested LDY rewards.\n * \n * @dev Intuition\n * \n * Lifecycle of a lockdrop pool is composed by 3 main phases:\n * 1) Deposit: During this phase, users can lock their underlying tokens.\n * 2) Claim: During this phase, users can claim their LDY rewards.\n * 3) Recovery: During this phase, owner can recover remaining ERC20 on the contract.\n * \n * Transitioning between two phases is manually triggered by contract's owner.\n * To ensure fair usage of this power and prevent potential misuse:\n * - the Recovery phase cannot start before 3 months after the end of rewards vesting,\n * - the Recovery phase cannot start before 3 months after the maximum lock end.\n * \n * Finally, note that this contract proxies main L-Token contract's functions:\n * - lock() --> deposit()\n * - instantUnlock() --> instantWithdrawal()\n * - requestUnlock() --> requestWithdrawal()\n * This design enables users to interact with the PreMining contract in a similar fashion\n * to the L-Token contract.\n * \n * @dev Definitions:\n * - Locker: An account that has locked underlying tokens in the pool.\n * \n * @custom:security-contact security@ledgity.com\n */\ncontract PreMining is Ownable2Step, Pausable {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Represents the lock information of an account.\n * @param amount Amount of underlying tokens locked.\n * @param duration Duration of the lock (in months).\n * @param hasUnlocked Whether the account has unlocked its locked tokens.\n * @param claimedRewards Amount of LDY rewards already claimed.\n * @param lockEndTimestamp Timestamp at which the account's lock ends.\n */\n struct AccountLock {\n uint240 amount;\n uint8 duration;\n bool hasUnlocked;\n uint216 claimedRewards;\n uint40 lockEndTimestamp;\n }\n\n /// @notice Holds the amount of LDY to be distributed to lockers.\n uint256 public immutable maxDistributedLDY;\n\n /// @notice Holds the maximum total amount of L-Tokens that can be locked.\n uint256 public immutable lockedHardCap;\n\n /// @notice Holds the minimum possible lock duration (in months).\n uint8 public immutable minLockDuration;\n\n /// @notice Holds the maximum possible lock duration (in months).\n uint8 public immutable maxLockDuration;\n\n /// @notice Holds the duration of LDY rewards vesting (in months).\n uint8 public immutable vestingDuration;\n\n /// @notice Holds a reference to the locked L-Token contract.\n LToken public immutable lToken;\n\n /// @notice Holds a reference to the L-Token underlying stablecoin.\n IERC20 public immutable underlyingToken;\n\n /// @notice Holds the max pool weight.\n uint256 public immutable maxWeight;\n\n /// @notice Holds a reference to the LDY token contract.\n IERC20 public ldyToken;\n\n /// @notice Holds lockers' participations informations.\n mapping(address => AccountLock) public accountsLocks;\n\n /// @notice Holds the total amount of locked underlying tokens.\n uint256 public totalLocked;\n\n /// @notice Holds whether the Deposit phase has ended.\n bool public hasDepositPhaseEnded;\n\n /// @notice Holds whether the Claim phase has started.\n bool public hasClaimPhaseStarted;\n\n /// @notice Holds whether the Recovery phase has started.\n bool public hasRecoveryPhaseStarted;\n\n /// @notice Holds the timestamp at which the Claim phase started.\n uint256 public claimPhaseStartTimestamp;\n\n /// @notice Holds an ordered queue of accounts that requested to unlock their tokens.\n address[] public unlockRequests;\n\n /// @notice Holds the index of the first request in the queue (a.k.a, next one to be processed).\n uint256 public unlockRequestsCursor;\n\n /// @notice Emitted to inform about a new lock/deposit.\n event Lock(address indexed account, uint256 amount, uint8 duration);\n\n /// @notice Top-level checks and code shared by both unlock functions.\n modifier safeUnlock() {\n // Ensure that the account's lock has ended\n require(accountsLocks[msg.sender].lockEndTimestamp <= block.timestamp, \"L68\");\n\n // Ensure the account hasn't already unlocked its tokens\n require(!accountsLocks[msg.sender].hasUnlocked, \"L69\");\n\n // Ensure the account has something to unlock\n require(accountsLocks[msg.sender].amount > 0, \"L70\");\n\n // Indicate that account has unlocked its tokens\n accountsLocks[msg.sender].hasUnlocked = true;\n _;\n }\n\n /**\n * @notice This constructor function etches the lockdrop terms in immutable states.\n * Ensuring that those terms cannot be modified after deployment.\n * @param lTokenAddress_ Address of the L-Token contract to use.\n * @param maxDistributedLDY_ Amount of LDY to be distributed to lockers.\n * @param lockedHardCap_ Maximum total amount of L-Tokens that can be locked.\n * @param minLockDuration_ Minimum possible lock duration (in months).\n * @param maxLockDuration_ Maximum possible lock duration (in months).\n * @param vestingDuration_ Duration of LDY rewards vesting (in months).\n */\n constructor(\n address lTokenAddress_,\n uint256 maxDistributedLDY_,\n uint256 lockedHardCap_,\n uint8 minLockDuration_,\n uint8 maxLockDuration_,\n uint8 vestingDuration_\n ) {\n // Ensure minLockDuration is at least 1 month\n require(minLockDuration_ >= 1, \"L72\");\n\n // Ensure minLockDuration is not greater than maxLockDuration\n require(minLockDuration_ <= maxLockDuration_, \"L73\");\n\n // Set immutable states\n lToken = LToken(lTokenAddress_);\n underlyingToken = IERC20(address(lToken.underlying()));\n lockedHardCap = lockedHardCap_;\n maxDistributedLDY = maxDistributedLDY_;\n minLockDuration = minLockDuration_;\n maxLockDuration = maxLockDuration_;\n vestingDuration = vestingDuration_;\n maxWeight = lockedHardCap * uint256(maxLockDuration);\n }\n\n /**\n * @notice Public implementation of Pausable's pausing and unpausing functions, but\n * restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Updates the LDY token contract address.\n * @dev As the first Ledgity Yield lockdrop campaigns will start before the LDY TGE,\n * this function allows the contract's owner to set the LDY token address once it\n * becomes available.\n * @param ldyTokenAddress Address of the LDY token contract.\n */\n function setLDYToken(address ldyTokenAddress) external onlyOwner {\n // Prevent owner from changing the LDY address after Claim phase has started\n require(!hasClaimPhaseStarted, \"L74\");\n\n // Set LDY token address\n ldyToken = IERC20(ldyTokenAddress);\n }\n\n /**\n * @notice Closes the Deposit phase. After calling this function, account won't be\n * able to lock additional underlying tokens anymore.\n */\n function endDepositPhase() external onlyOwner {\n hasDepositPhaseEnded = true;\n }\n\n /**\n * @notice Opens the Claim phase. After calling this function, lockers will be able\n * to start claiming their LDY rewards.\n */\n function startClaimPhase() external onlyOwner {\n // Ensure Claim phase has not already started\n require(!hasClaimPhaseStarted, \"L76\");\n\n // Ensure that LDY token address is available\n require(address(ldyToken) != address(0), \"L77\");\n\n // Set Claim phase as started and store the start timestamp\n hasClaimPhaseStarted = true;\n claimPhaseStartTimestamp = block.timestamp;\n }\n\n /**\n * @notice Opens the Recovery phase. After calling this function, the contract owner\n * will be able to recover remaining ERC20 tokens on the contract.\n * Note that this won't close the Claim phase and lockers will still be able to claim\n * their LDY rewards.\n */\n function startRecoveryPhase() external onlyOwner {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L79\");\n\n // Compute some durations in seconds\n uint256 threeMonthsInSecond = 3 * 30 days;\n uint256 vestingInSecond = uint256(vestingDuration) * 30 days;\n uint256 maxLockInSecond = uint256(maxLockDuration) * 30 days;\n\n // Compute timestamp of vesting end + 3 months\n uint256 afterVestingTimestamp = claimPhaseStartTimestamp +\n vestingInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the end of reward vesting\n // This prevents owner from recovering LDY before lockers can claim their rewards\n require(block.timestamp >= afterVestingTimestamp, \"L80\");\n\n // Compute end of maximum lock + 3 months\n // Note that claimPhaseStartTimestamp is used for simplicity even if it can exist a time\n // span between Deposit and Claim phases.\n uint256 afterMaxLockTimestamp = claimPhaseStartTimestamp +\n maxLockInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the maximum lock end\n // This prevents owner from recovering underlying tokens before lockers can unlock those\n require(block.timestamp >= afterMaxLockTimestamp, \"L81\");\n\n // Set recovery phase as started\n hasRecoveryPhaseStarted = true;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address. Will revert if\n * recovery phase has not started yet or if the contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) external onlyOwner {\n // Ensure recovery phase has started\n require(hasRecoveryPhaseStarted, \"L82\");\n\n // Create a reference to token's contract\n IERC20 tokenContract = IERC20(tokenAddress);\n\n // Ensure there is enough tokens to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L83\");\n\n // Transfer the recovered token amount to the sender (owner)\n tokenContract.safeTransfer(msg.sender, amount);\n }\n\n /**\n * @notice Compute the total amount of LDY rewards that a given account is eligible to.\n * @dev Note: This function neither considers vesting nor already claimed rewards.\n * @param account The account to compute the eligible rewards of.\n * @return The total amount of LDY rewards that the account is eligible to.\n */\n function eligibleRewardsOf(address account) public view returns (uint256) {\n // Compute account's lock weight\n uint256 lockerWeight = accountsLocks[account].amount * accountsLocks[account].duration;\n\n // Compute amount of LDY that this locker is eligible to\n if (maxWeight == 0) return 0;\n else return (maxDistributedLDY * lockerWeight) / maxWeight;\n }\n\n /**\n * @notice Allows locking a specified amount of underlying tokens for a given duration.\n * By locking, an account became eligible to a portion of the distributed LDY rewards.\n * @dev This function proxies LToken.deposit()\n * @dev Lockers can extend their lock duration by calling this function again with a\n * greater duration and 0 as amount.\n * @param amount Amount of underlying tokens to lock.\n * @param duration Duration of the lock (in months).\n */\n function lock(uint256 amount, uint8 duration) external whenNotPaused {\n // Ensure Deposit phase has not ended yet\n require(!hasDepositPhaseEnded, \"L84\");\n\n // Ensure account hasn't already unlocked a past lock\n require(!accountsLocks[msg.sender].hasUnlocked, \"L71\");\n\n // Ensure lock duration is in valid range\n require(duration >= minLockDuration && duration <= maxLockDuration, \"L85\");\n\n // Ensure it won't exceed the hardcap\n require(totalLocked + amount <= uint256(lockedHardCap), \"L86\");\n\n // Increase account's locked amount\n accountsLocks[msg.sender].amount += uint240(amount);\n\n // Increase total locked amount accordingly\n totalLocked += amount;\n\n // Use existing lock duration if greater than the new one\n uint8 existingDuration = accountsLocks[msg.sender].duration;\n uint8 appliedDuration = existingDuration > duration ? existingDuration : duration;\n\n // Update account's lock duration\n accountsLocks[msg.sender].duration = appliedDuration;\n\n // Update account's lock end timestamp\n accountsLocks[msg.sender].lockEndTimestamp = uint40(\n block.timestamp + uint40(appliedDuration) * 30 days\n );\n\n // Emit a Lock event\n emit Lock(msg.sender, amount, appliedDuration);\n\n // If amount is 0, skip deposit\n if (amount == 0) return;\n\n // Transfer underlyingToken from account to contract\n underlyingToken.safeTransferFrom(msg.sender, address(this), amount);\n\n // Deposit USDC in the L-Token contract\n underlyingToken.safeApprove(address(lToken), amount);\n lToken.deposit(amount);\n }\n\n /**\n * @notice Allows the caller to instaneously unlock its locked amount of underlying\n * tokens.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestUnlock() function otherwise.\n */\n function instantUnlock() external whenNotPaused safeUnlock {\n // Retrieve underlying tokens from the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.instantWithdrawal(unlockedAmount);\n\n // Transfer underlying tokens back to caller\n underlyingToken.safeTransfer(msg.sender, unlockedAmount);\n }\n\n /**\n * @notice Allows the call to request for the unlocking of its locked amount of\n * underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n */\n function requestUnlock() external payable whenNotPaused safeUnlock {\n // Put account in the unlock requests queue\n unlockRequests.push(msg.sender);\n\n // Request underlying tokens to the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.requestWithdrawal{value: msg.value}(unlockedAmount);\n }\n\n /**\n * @notice Processes queued unlock requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n */\n function processUnlockRequests() external onlyOwner {\n // Store the current request ID to process\n uint256 processedId = unlockRequestsCursor;\n\n // Loop over remaining requests\n while (processedId < unlockRequests.length) {\n // Prevent OOG by stopping request processing if there is not enough gas left\n // to continue the loop and properly end the function call.\n if (gasleft() < 45000) break;\n\n // Retrieve the request account\n address unlockAccount = unlockRequests[processedId];\n\n // Retrieve the unlocked amount\n uint256 unlockAmount = accountsLocks[unlockAccount].amount;\n\n // If the request has already been processed, skip it\n if (unlockAccount != address(0)) {\n // If the contract doesn't hold enough underlying tokens to process the request, stop here\n if (underlyingToken.balanceOf(address(this)) < unlockAmount) break;\n\n // Delete the request\n delete unlockRequests[processedId];\n\n // Transfer underlying back to account\n underlyingToken.safeTransfer(unlockAccount, unlockAmount);\n }\n\n // Increment processed request ID\n processedId++;\n }\n\n // Write back the cursor in storage\n unlockRequestsCursor = processedId;\n }\n\n /**\n * @notice Computes the amount of LDY rewards available to claim for a given account.\n * @dev This function considers vesting and already claimed rewards.\n * @param account The account to compute the available rewards of.\n * @return The amount of LDY rewards available to claim.\n */\n function availableToClaim(address account) public view returns (uint256) {\n // Compute total amount of rewards allocated to this locker\n uint256 totalEligibleRewards = eligibleRewardsOf(account);\n\n // Compute vesting duration in seconds\n uint256 vestingInSeconds = uint256(vestingDuration) * 30 days;\n\n // Compute elapsed months since claim phase started, and cap it to vesting duration\n uint256 elapsedTime = block.timestamp - claimPhaseStartTimestamp;\n if (elapsedTime > vestingInSeconds) elapsedTime = vestingInSeconds;\n\n // Compute total available to claim (proportionally to elapsed time)\n uint256 totalAvailableToClaim = (totalEligibleRewards * elapsedTime) / vestingInSeconds;\n\n // Else return net claimable (available minus already claimed)\n return totalAvailableToClaim - accountsLocks[account].claimedRewards;\n }\n\n /// @notice Allows the caller to claim its available LDY rewards.\n function claimRewards() external whenNotPaused {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L87\");\n\n // Compute claimable LDY rewards\n uint256 claimableLDY = availableToClaim(msg.sender);\n\n // Increase account claimed amount accordingly\n accountsLocks[msg.sender].claimedRewards += uint216(claimableLDY);\n\n // Transfer rewards to account\n ldyToken.safeTransfer(msg.sender, claimableLDY);\n }\n}\n" + } + }, + "settings": { + "evmVersion": "london", + "optimizer": { + "enabled": true, + "runs": 100 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/contracts/hardhat/deployments/arbitrum/solcInputs/b5b3f1cfe4b89ed5996f5a0ba11d1ffb.json b/contracts/hardhat/deployments/arbitrum/solcInputs/b5b3f1cfe4b89ed5996f5a0ba11d1ffb.json new file mode 100644 index 00000000..54faa9f3 --- /dev/null +++ b/contracts/hardhat/deployments/arbitrum/solcInputs/b5b3f1cfe4b89ed5996f5a0ba11d1ffb.json @@ -0,0 +1,165 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeTo(address newImplementation) public virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../../../security/PausableUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract unpausable.\n */\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\n function __ERC20Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __ERC20Pausable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Wrapper.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../utils/SafeERC20Upgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of the ERC20 token contract to support token wrapping.\n *\n * Users can deposit and withdraw \"underlying tokens\" and receive a matching number of \"wrapped tokens\". This is useful\n * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the\n * wrapping of an existing \"basic\" ERC20 into a governance token.\n *\n * _Available since v4.2._\n *\n * @custom:storage-size 51\n */\nabstract contract ERC20WrapperUpgradeable is Initializable, ERC20Upgradeable {\n IERC20Upgradeable private _underlying;\n\n function __ERC20Wrapper_init(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n __ERC20Wrapper_init_unchained(underlyingToken);\n }\n\n function __ERC20Wrapper_init_unchained(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n require(underlyingToken != this, \"ERC20Wrapper: cannot self wrap\");\n _underlying = underlyingToken;\n }\n\n /**\n * @dev See {ERC20-decimals}.\n */\n function decimals() public view virtual override returns (uint8) {\n try IERC20MetadataUpgradeable(address(_underlying)).decimals() returns (uint8 value) {\n return value;\n } catch {\n return super.decimals();\n }\n }\n\n /**\n * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\n */\n function underlying() public view returns (IERC20Upgradeable) {\n return _underlying;\n }\n\n /**\n * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\n */\n function depositFor(address account, uint256 amount) public virtual returns (bool) {\n address sender = _msgSender();\n require(sender != address(this), \"ERC20Wrapper: wrapper can't deposit\");\n SafeERC20Upgradeable.safeTransferFrom(_underlying, sender, address(this), amount);\n _mint(account, amount);\n return true;\n }\n\n /**\n * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\n */\n function withdrawTo(address account, uint256 amount) public virtual returns (bool) {\n _burn(_msgSender(), amount);\n SafeERC20Upgradeable.safeTransfer(_underlying, account, amount);\n return true;\n }\n\n /**\n * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal\n * function that can be exposed with access control if desired.\n */\n function _recover(address account) internal virtual returns (uint256) {\n uint256 value = _underlying.balanceOf(address(this)) - totalSupply();\n _mint(account, value);\n return value;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable2Step.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "contracts/src/abstracts/base/BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"../GlobalOwnableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"../GlobalRestrictableUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../RecoverableUpgradeable.sol\";\n\n/**\n * @title BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract acts as a base for numerous contracts in this codebase,\n * minimizing code repetition and enhancing readability and maintainability.\n *\n * @dev For further details, see \"Base\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract BaseUpgradeable is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n GlobalPausableUpgradeable,\n GlobalRestrictableUpgradeable,\n RecoverableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_\n ) internal onlyInitializing {\n __UUPSUpgradeable_init();\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n __Recoverable_init_unchained();\n }\n\n function __Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/base/ERC20BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./BaseUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\n\n/**\n * @title ERC20BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract is an extension of BaseUpgradeable intended to be used\n * as a base for ERC20 tokens contracts.\n *\n * @dev For further details, see \"ERC20BaseUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract ERC20BaseUpgradeable is\n ERC20Upgradeable,\n BaseUpgradeable,\n ERC20PausableUpgradeable\n{\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param name_ The display name of the token.\n * @param symbol_ The symbol of the token.\n */\n function __ERC20Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n string memory name_,\n string memory symbol_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __ERC20_init(name_, symbol_);\n __ERC20Pausable_init_unchained();\n }\n\n function __ERC20Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and PausableUpgradeable parent contracts.\n * The GlobalPausableUpgradeable version is preferred because it checks the pause\n * state from the GlobalPause contract.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, PausableUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @dev Required override of _beforeTokenTransfer() which is implemented by both\n * ERC20PausableUpgradeable and ERC20Upgradeable parent contracts.\n * The ERC20PausableUpgradeable version is preferred because it also checks that\n * the contract is not paused before allowing the transfer.\n * @inheritdoc ERC20PausableUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n )\n internal\n virtual\n override(ERC20PausableUpgradeable, ERC20Upgradeable)\n whenNotPaused\n notBlacklisted(from)\n notBlacklisted(to)\n {\n ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalOwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {GlobalOwner} from \"../GlobalOwner.sol\";\n\n/**\n * @title GlobalOwnableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\n * contract (see GlobalOwner.sol). This design facilitates centralized management\n * of ownership for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalOwner state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalOwnableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\n /**\n * @notice The GlobalOwner contract the ownership will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalOwner private _globalOwner;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init_unchained(globalOwner_);\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\n // the initial _owner value, calling it would have no effect.\n }\n\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\n _globalOwner = GlobalOwner(globalOwner_);\n }\n\n /**\n * @notice Retrieves the address of GlobalOwner contract.\n * @return The address of the GlobalOwner contract.\n */\n function globalOwner() public view returns (address) {\n return address(_globalOwner);\n }\n\n /**\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\n * from the GlobalOwner contract instead.\n * @return The address of the owner\n */\n function owner() public view override returns (address) {\n return _globalOwner.owner();\n }\n\n /**\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function transferOwnership(address newOwner) public view override onlyOwner {\n newOwner; // Silence unused variable compiler warning\n revert(\"L8\");\n }\n\n /**\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function renounceOwnership() public view override onlyOwner {\n revert(\"L65\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalPause} from \"../GlobalPause.sol\";\n\n/**\n * @title GlobalPausableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a pause state from the specified GlobalPause\n * contract (see GlobalPause.sol). This design facilitates centralized management of\n * pause state for all the Ledgity Yield contracts.\n *\n * @dev Security measure\n * The _globalPause state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalPausableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\n /**\n * @notice The GlobalPause contract the pause state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalPause private _globalPause;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalPause_ The address of the GlobalPause contract.\n */\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n }\n\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\n _globalPause = GlobalPause(globalPause_);\n }\n\n /**\n * @notice Retrieves the address of GlobalPause contract.\n * @return The address of the GlobalPause contract.\n */\n function globalPause() public view returns (address) {\n return address(_globalPause);\n }\n\n /**\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\n * from the GlobalPause contract instead.\n * @return Whether the contract is paused or not.\n */\n function paused() public view virtual override returns (bool) {\n return _globalPause.paused();\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalRestrictableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalBlacklist} from \"../GlobalBlacklist.sol\";\n\n/**\n * @title GlobalRestrictableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a blacklist state from the specified\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\n * centralized management of a blacklist for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalBlacklist state must be set at initialization time and, for evident\n * security reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalRestrictableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalRestrictableUpgradeable is Initializable {\n /**\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalBlacklist private _globalBlacklist;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n }\n\n function __GlobalRestrictable_init_unchained(\n address globalBlacklist_\n ) internal onlyInitializing {\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\n }\n\n /**\n * @notice Retrieves the address of GlobalBlacklist contract.\n * @return The address of the GlobalBlacklist contract.\n */\n function globalBlacklist() public view returns (address) {\n return address(_globalBlacklist);\n }\n\n /**\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n */\n modifier notBlacklisted(address account) {\n require(isBlacklisted(account) == false, \"L9\");\n _;\n }\n\n /**\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n * @return Whether the account is blacklisted.\n */\n function isBlacklisted(address account) internal view returns (bool) {\n return _globalBlacklist.isBlacklisted(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/InvestUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"./GlobalPausableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"./GlobalRestrictableUpgradeable.sol\";\nimport \"./base/BaseUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../abstracts/RecoverableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {APRHistory as APRH} from \"../libs/APRHistory.sol\";\nimport {SUD} from \"../libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title InvestUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with utilities to manage an invested token,\n * users' investment periods, rewards calculations, virtual balances, and auto-compounding.\n *\n * @dev Intuition:\n * This contract primarily exists for code splitting and reusability. It unburdens the\n * LToken contract code, making it easier to understand and maintain.\n *\n * This contract is generic because it may be used in the LDYStaking contract in the future.\n *\n * @dev Definitions:\n * - Investment: The act of depositing or investing tokens into the contract.\n * - Investment period: Time between the last invested amount change and the present.\n * - Virtual balance: Temporary storage for account rewards, used when those can't be\n * distributed between investment periods.\n * - Rewards redirection: Mechanism allowing an account to redirect its rewards to another.\n *\n * @dev Derived contract must:\n * - Set invested token during initialization\n * - Implement _investmentOf() function\n * - (optionally) Implement _distributeRewards() function\n *\n * @dev For further details, see \"InvestmentUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract InvestUpgradeable is BaseUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using APRH for APRH.Pack[];\n\n /**\n * @notice Represents an account's investment period.\n * @param timestamp The timestamp of the most recent rewards distribution.\n * @param ref The reference of the last APR checkpoint at that timestamp.\n */\n struct InvestmentPeriod {\n uint40 timestamp; // Supports dates up to 20/02/36812\n APRH.Reference ref;\n }\n\n /**\n * @notice Represents the investment details of an account.\n * @param period The current investment period of the account.\n * @param virtualBalance May hold a part of account rewards until they are claimed.\n */\n struct AccountDetails {\n InvestmentPeriod period;\n uint256 virtualBalance;\n }\n\n /// @notice Holds a reference to the invested token's contract.\n IERC20Upgradeable private _invested;\n\n /// @notice Holds investment details of each account.\n mapping(address => AccountDetails) internal accountsDetails;\n\n /// @notice Holds an history of the APR value over time (see APRHistory.sol).\n APRH.Pack[] private _aprHistory;\n\n /// @notice Holds active rewards redirections in both from->to and to->from[] ways.\n mapping(address => address) public rewardsRedirectsFromTo;\n mapping(address => address[]) public rewardsRedirectsToFrom;\n\n /// @notice Is used to prevent infinite loop in _beforeInvestmentChange().\n bool private _isClaiming;\n\n /**\n * @notice Emitted to inform listeners about a change in the APR's value.\n * @param newAPRUD7x3 The new APR in UD7x3 format.\n */\n event APRChangeEvent(uint16 newAPRUD7x3);\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param invested_ The address of the invested token contract.\n */\n function __Invest_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address invested_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __Invest_init_unchained(invested_);\n }\n\n function __Invest_init_unchained(address invested_) internal onlyInitializing {\n // Set invested token\n _invested = IERC20Upgradeable(invested_);\n\n // Define initial APR to 0%. This would prevent getAPR() from reverting because\n // of an empty APR history\n _aprHistory.setAPR(0);\n }\n\n /**\n * @notice Retrieves the reference to the invested token contract.\n * @return The reference to the invested token contract.\n */\n function invested() public view returns (IERC20Upgradeable) {\n return _invested;\n }\n\n /**\n * @notice Updates the investment APR. Restricted to owner.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(uint16 aprUD7x3) public onlyOwner {\n _aprHistory.setAPR(aprUD7x3);\n emit APRChangeEvent(aprUD7x3);\n }\n\n /**\n * @notice Retrieves the most recently set APR.\n * @return The current APR in UD7x3 format.\n */\n function getAPR() public view returns (uint16) {\n return _aprHistory.getAPR();\n }\n\n /**\n * @notice Enables redirection of rewards from one account to another.\n * @param from The address of the account to redirect rewards from.\n * @param to The address of the account to redirect rewards to.\n */\n function startRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure the address is not already redirecting rewards\n require(rewardsRedirectsFromTo[from] == address(0), \"L62\");\n\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L12\");\n require(to != address(0), \"L13\");\n\n // Ensure 'from' and 'to' addresses are distinct\n require(from != to, \"L14\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L15\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Activate rewards redirection\n rewardsRedirectsFromTo[from] = to;\n rewardsRedirectsToFrom[to].push(from);\n }\n\n /**\n * @notice Disable an active rewards redirection.\n * @param from The address of the account to stop redirecting rewards from.\n * @param to The address of the account to stop redirecting rewards to.\n */\n function stopRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L16\");\n require(to != address(0), \"L17\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L18\");\n\n // Ensure a rewards redirection was active\n require(rewardsRedirectsFromTo[from] == to, \"L19\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Retrieve 'from' index in the redirection array of 'to'\n int256 fromIndex = -1;\n for (uint256 i = 0; i < rewardsRedirectsToFrom[to].length; i++) {\n if (rewardsRedirectsToFrom[to][i] == from) {\n fromIndex = int256(i);\n break;\n }\n }\n\n // fromIndex should never be -1 at this point\n assert(fromIndex >= 0);\n\n // Deactivate rewards redirection\n rewardsRedirectsFromTo[from] = address(0);\n rewardsRedirectsToFrom[to][uint256(fromIndex)] = rewardsRedirectsToFrom[to][\n rewardsRedirectsToFrom[to].length - 1\n ];\n rewardsRedirectsToFrom[to].pop();\n }\n\n /**\n * @notice Retrieves the total amount of tokens invested by the given account.\n * @dev Derived contracts must implement this function.\n * @param account The account to get the investment of.\n * @return The total amount of tokens invested by the given account.\n */\n function _investmentOf(address account) internal view virtual returns (uint256);\n\n /**\n * @notice Distributes a specified amount of rewards to a given account.\n * @dev Derived contracts may optionally implement this function.\n * @dev Implementations must return true to indicate a successful distribution, and\n * false otherwise. If it returns false, the rewards will be added to the account's\n * virtual balance, in order to be claimed later.\n * @param account The account to claim the rewards of.\n * @param amount The amount of rewards to claim.\n * @return Whether the rewards distribution was successfull.\n */\n function _distributeRewards(address account, uint256 amount) internal virtual returns (bool) {\n account; // Silence unused variables warning\n amount;\n return false;\n }\n\n /**\n * @notice Computes the rewards accrued over a specified period of time, based on a\n * given APR and amount of invested tokens.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param beginTimestamp The moment the period commenced.\n * @param endTimestamp The moment the period concluded.\n * @param aprUD7x3 The APR during this period, in UD7x3 format.\n * @param investedAmount The amount of tokens deposited/invested during the period.\n * @return The amount of rewards generated during the period.\n */\n function _calculatePeriodRewards(\n uint40 beginTimestamp,\n uint40 endTimestamp,\n uint16 aprUD7x3,\n uint256 investedAmount\n ) internal view returns (uint256) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Compute the number of elapsed years\n uint256 elapsedTimeSUD = SUD.fromInt(endTimestamp - beginTimestamp, d);\n uint256 elapsedYearsSUD = (elapsedTimeSUD * SUD.fromInt(1, d)) / SUD.fromInt(365 days, d);\n\n // Compute the growth in invested amount (thanks to rewards)\n uint256 aprSUD = SUD.fromRate(aprUD7x3, d);\n uint256 growthSUD = (elapsedYearsSUD * aprSUD) / SUD.fromInt(1, d);\n\n // Compute and return the rewards\n uint256 investedAmountSUD = SUD.fromAmount(investedAmount, d);\n uint256 rewardsSUD = (investedAmountSUD * growthSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(rewardsSUD, d);\n }\n\n /**\n * @notice Computes the sum of given account's invested amount, plus invested amount\n * of all accounts that recursively redirect rewards to this account.\n * @param account The account to calculate the deep investment of.\n * @return deepInvestedAmount The deep invested amount.\n */\n function _deepInvestmentOf(address account) internal view returns (uint256 deepInvestedAmount) {\n // Consider account's direct investment\n deepInvestedAmount += _investmentOf(account);\n\n // But also the deep investments of all accounts redirecting rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n deepInvestedAmount += _deepInvestmentOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Computes the amount of unclaimed/undistributed rewards of a given account.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param account The account to calculate the unclaimed rewards of.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n * @return rewards The amount of unclaimed/undistributed rewards of the given account.\n */\n function _rewardsOf(\n address account,\n bool autocompound\n ) internal view returns (uint256 rewards) {\n // Retrieve account's investment details\n AccountDetails memory details = accountsDetails[account];\n\n // Retrieve account's deep invested amount\n uint256 investedAmount = _deepInvestmentOf(account);\n\n // Return 0 if the account has never invested or has no invested amount\n if (details.period.timestamp == 0 || investedAmount == 0) return 0;\n\n // Retrieve reference and data of APR checkpoint at which started investment period\n APRH.Reference memory currRef = details.period.ref;\n APRH.CheckpointData memory currCheckpoint = _aprHistory.getDataFromReference(currRef);\n\n // Retrieve reference of latest APR checkpoint\n APRH.Reference memory latestRef = _aprHistory.getLatestReference();\n\n // 1) Fill rewards with virtual balance (rewards not claimed/distributed yet)\n // See \"InvestUpgradeable > Yield calculation > 1)\" section of the whitepaper\n rewards = details.virtualBalance;\n\n // If start checkpoint is not the latest one\n if (!APRH.eq(currRef, latestRef)) {\n // Retrieve reference and data of APR checkpoint that comes after start checkpoint\n APRH.Reference memory nextRef = APRH.incrementReference(currRef);\n APRH.CheckpointData memory nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // 2) Calculate rewards from investment period start to next checkpoint\n // See \"InvestUpgradeable > Yield calculation > 2)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n\n // 3) Calculate rewards for each crossed pair of checkpoints\n // See \"InvestUpgradeable > Yield calculation > 3)\" section of the whitepaper\n while (true) {\n // Set next checkpoint as the current one\n currRef = nextRef;\n currCheckpoint = nextCheckpoint;\n\n // Break if current checkpoint is the latest one\n if (APRH.eq(currRef, latestRef)) break;\n\n // Else, retrieve the new next checkpoint\n nextRef = APRH.incrementReference(currRef);\n nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // Calculate rewards between the current pair of checkpoints\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n\n // 4) Calculate rewards from the latest checkpoint to now\n // See \"InvestUpgradeable > Yield calculation > 4)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n } else {\n // 2.bis) Calculate rewards from investment period start to now\n // See \"InvestUpgradeable > Yield calculation > 2.bis)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n }\n\n /**\n * @notice Recursively resets the investment period of the specified account and of\n * all accounts that directly or indirectly redirect rewards to this account.\n * @param account The account to deeply reset the investment period of.\n */\n function _deepResetInvestmentPeriodOf(address account) internal {\n // Reset account investment period timestamp and APR checkpoint to latest ones\n accountsDetails[account].period.timestamp = uint40(block.timestamp);\n accountsDetails[account].period.ref = _aprHistory.getLatestReference();\n\n // Also reset the ones of all accounts that recursively redirect rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n _deepResetInvestmentPeriodOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Hook to be invoked before the invested amount of an account changes. It\n * ensures that rewards are distributed and that account's investment period is reset.\n * @param account The account whose invested amount is going to change.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n */\n function _beforeInvestmentChange(address account, bool autocompound) internal {\n // This hook is called inside LToken._beforeTokenTransfer() and as new tokens are\n // minted in LToken._distributeRewards(), this guards against infinite loop.\n if (_isClaiming) return;\n\n // LToken._beforeTokenTransfer() calls this hook for both involved addresses.\n // As first call will treat both addresses, the second call would be redundant.\n // Therefore, we skip accounts already processed in this block to save up some gas.\n if (accountsDetails[account].period.timestamp == uint40(block.timestamp)) return;\n\n // If account redirects its rewards\n address redirectRewardsTo = rewardsRedirectsFromTo[account];\n if (redirectRewardsTo != address(0)) {\n // Call hook on redirection target (this will indirectly reset the investment\n // of this source account) and return\n _beforeInvestmentChange(redirectRewardsTo, autocompound);\n return;\n }\n\n // Else, compute account's undistributed/unclaimed rewards\n uint256 rewards = _rewardsOf(account, autocompound);\n\n // If there are some rewards\n if (rewards > 0) {\n // Try to distribute rewards to account\n _isClaiming = true;\n bool distributed = _distributeRewards(account, rewards);\n _isClaiming = false;\n\n // If rewards have not been distributed, accumulate them in account's virtual balance\n if (!distributed) accountsDetails[account].virtualBalance = rewards;\n }\n\n // Finally, deeply reset investment period of the account\n _deepResetInvestmentPeriodOf(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/RecoverableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Conracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title RecoverableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with helper functions allowing the recovery of\n * assets accidentally sent to them.\n *\n * @dev Where are utilities Ether, ERC721, etc.?\n * This abstract contract currently supports only ERC20 tokens. Derived contracts\n * in this codebase currently do not implement the necessary functions to receive Ether\n * or ERC721/ERC1155 tokens, so no recovery functions are provided for these assets.\n *\n * @dev For further details, see \"RecoverableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init(globalOwner_);\n __Recoverable_init_unchained();\n }\n\n function __Recoverable_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Recovers a specified amount of a given token address. Will fail if the\n * contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\n // Ensure the specified amount is not zero\n require(amount > 0, \"L10\");\n\n // Create a reference to token's contract\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\n\n // Ensure there is enough token to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L11\");\n\n // Transfer the recovered token amount to the sender\n tokenContract.safeTransfer(_msgSender(), amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/GlobalBlacklist.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalBlacklist\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global mapping of blacklisted accounts shared by all contracts of the\n * Ledgity Yield codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\n * and getter functions to easily check against this global blacklist.\n *\n * @dev For further details, see \"GlobalBlacklist\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\n /**\n * @notice Mapping of accounts to their blacklist status.\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\n */\n mapping(address => bool) private _list;\n\n /// @dev Emitted when `account` is blacklisted.\n event Blacklisted(address account);\n\n /// @dev Emitted when `account` is unblacklisted.\n event Unblacklisted(address account);\n\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @notice Adds a given account to the blacklist.\n * @param account The account's address to be blacklisted.\n */\n function blacklist(address account) external onlyOwner {\n require(account != address(0), \"L20\");\n _list[account] = true;\n emit Blacklisted(account);\n }\n\n /**\n * @notice Removes a given account from the blacklist.\n * @param account The account's address to be un-blacklisted.\n */\n function unBlacklist(address account) external onlyOwner {\n _list[account] = false;\n emit Unblacklisted(account);\n }\n\n /**\n * @notice Checks whether a given account is blacklisted.\n * @param account Address of the account to check.\n * @return 'true' if the account is blacklisted, 'false' otherwise\n */\n function isBlacklisted(address account) external view returns (bool) {\n // Gas optimization: Avoid accessing storage if account is the zero address\n // (e.g, during a mint or a burn of tokens)\n if (account == address(0)) return false;\n\n // Else, return current account's blacklist status\n return _list[account];\n }\n}\n" + }, + "contracts/src/GlobalOwner.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {Ownable2StepUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\n/**\n * @title GlobalOwner\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds the address of a global owner account shared by all contracts of the\n * Ledgity Yield's codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\n * owner() function that retrieves the owner's address from this contract instead.\n *\n * @dev For further details, see \"GlobalOwner\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n */\n function initialize() public initializer {\n __Ownable2Step_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n}\n" + }, + "contracts/src/GlobalPause.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalPause\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global pause state shared by all contracts of the Ledgity Yield\n * codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\n * paused() function that retrieves the pause state from this contract instead.\n *\n * @dev For further details, see \"GlobalPause\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalPause is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n PausableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\n * but restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n}\n" + }, + "contracts/src/interfaces/ITransfersListener.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\ninterface ITransfersListener {\n function onLTokenTransfer(address from, address to, uint256 amount) external;\n}\n" + }, + "contracts/src/LDYStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {BaseUpgradeable} from \"./abstracts/base/BaseUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title LDYStaking\n * @custom:security-contact security@ledgity.com\n *\n * @dev This contract implements tierOf() function from LDYStaking as it's the only\n * one the LToken contract relies on.\n *\n * @custom:security-contact security@ledgity.com\n */\ncontract LDYStaking is BaseUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Represents a user staking info in array.\n * @param stakedAmount Amount of the stake.\n * @param unStakeAt Unstake at.\n * @param duration Staking period in seconds.\n * @param rewardPerTokenPaid Reward per token paid.\n * @param rewards Rewards to be claimed.\n */\n struct StakingInfo {\n uint256 stakedAmount;\n uint256 unStakeAt;\n uint256 duration;\n uint256 rewardPerTokenPaid;\n uint256 rewards;\n }\n\n /**\n * @notice Represent duration and multiplier per each stake option.\n * @param duration Staking period in seconds.\n * @param multiplier Token weight\n */\n struct StakeDurationInfo {\n uint256 duration;\n uint256 multiplier;\n }\n\n /// @notice Decimals of multiplier\n uint256 public constant MULTIPLIER_BASIS = 1e4;\n\n /// @notice Stake and Reward token.\n IERC20Upgradeable public stakeRewardToken;\n\n /// @notice Minimal stake duration for perks.\n uint256 public stakeDurationForPerks;\n\n /// @notice Minimal stake amount for perks.\n uint256 public stakeAmountForPerks;\n\n /// @notice Stake durations info array.\n StakeDurationInfo[] public stakeDurationInfos;\n\n /// @notice Duration of the rewards (in seconds).\n uint256 public rewardsDuration;\n\n /// @notice Timestamp of when the rewards finish.\n uint256 public finishAt;\n\n /// @notice Timestamp of the reward updated.\n uint256 public lastUpdateTime;\n\n /// @notice Reward per second(total rewards / duration).\n uint256 public rewardRatePerSec;\n\n /// @notice Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\n uint256 public rewardPerTokenStored;\n\n /// @notice Total staked amounts.\n uint256 public totalStaked;\n\n // Total staked amounts with multiplier applied\n uint256 public totalWeightedStake;\n\n /// @notice User stakingInfo map, user address => array of the staking info\n mapping(address => StakingInfo[]) public userStakingInfo;\n\n /// @notice Total rewards amount.\n uint256 public totalRewards;\n\n /**\n * @notice Emitted when users stake token\n * @param user User address\n * @param stakeIndex Latest index of user staking pool\n * @param amount Staked amount\n */\n event Staked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users unstake token\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param amount Staked amount\n */\n event Unstaked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users claim rewards\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param reward Reward token amount\n */\n event RewardPaid(address indexed user, uint256 stakeIndex, uint256 reward);\n\n /**\n * @notice Emitted when admin add rewards.\n * @param rewardAmount Reward amount added by admin.\n * @param rewardPerSec RewardRatePerSec updated.\n */\n event NotifiedRewardAmount(uint256 rewardAmount, uint256 rewardPerSec);\n\n /**\n * @notice Holds a mapping of addresses that default to the highest staking tier.\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\n */\n mapping(address => bool) public highTierAccounts;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\n * @dev This function is intended for setting initial values for the contract's state variables.\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param stakeRewardToken_ The address of stake and reward token(LDY token).\n * @param stakeDurationInfos_ Available Staking Durations.\n * @param stakeDurationForPerks_ Minimal staking duration for perks.\n * @param stakeAmountForPerks_ Minimal staking amount for perks.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address stakeRewardToken_,\n StakeDurationInfo[] memory stakeDurationInfos_,\n uint256 stakeDurationForPerks_,\n uint256 stakeAmountForPerks_\n ) public initializer {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n stakeRewardToken = IERC20Upgradeable(stakeRewardToken_);\n uint stakeDurationInfosLength = stakeDurationInfos_.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n stakeDurationInfos.push(stakeDurationInfos_[i]);\n }\n stakeDurationForPerks = stakeDurationForPerks_;\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n // --------------------\n // MUTATIVE FUNCTIONS\n // --------------------\n\n /**\n * @notice Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\n * @dev Emits a `Staked` event upon successful staking.\n * @param amount The amount of tokens to stake.\n * @param stakeDurationIndex The Index of stakeDurationInfos array.\n */\n function stake(\n uint256 amount,\n uint8 stakeDurationIndex\n ) external nonReentrant whenNotPaused notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(stakeDurationIndex <= stakeDurationInfos.length - 1, \"Invalid staking period\");\n\n _updateReward(address(0), 0);\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[stakeDurationIndex];\n StakingInfo memory stakingInfo = StakingInfo({\n stakedAmount: amount,\n unStakeAt: block.timestamp + stakeDurationInfo.duration,\n duration: stakeDurationInfo.duration,\n rewardPerTokenPaid: rewardPerTokenStored,\n rewards: 0\n });\n\n // check whether account is eligible for benefit from the protocol\n if (stakeDurationInfo.duration >= stakeDurationForPerks && amount >= stakeAmountForPerks) {\n highTierAccounts[_msgSender()] = true;\n }\n\n userStakingInfo[_msgSender()].push(stakingInfo);\n\n uint256 stakeIndex = userStakingInfo[_msgSender()].length - 1;\n uint256 weightedStake = (amount * stakeDurationInfo.multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake += weightedStake;\n totalStaked += amount;\n\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit Staked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Withdraw staked tokens after stakeDuration has passed.\n * @dev Emits a `Unstaked` event upon successful withdrawal.\n * On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\n * @param amount The amount of tokens to withdraw.\n * @param stakeIndex The index of user staking pool\n */\n function unstake(\n uint256 amount,\n uint256 stakeIndex\n ) external nonReentrant notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n require(\n block.timestamp >= userStakingInfo[_msgSender()][stakeIndex].unStakeAt,\n \"Cannot unstake during staking period\"\n );\n require(\n amount <= userStakingInfo[_msgSender()][stakeIndex].stakedAmount,\n \"Insufficient unstake amount\"\n );\n\n _updateReward(_msgSender(), stakeIndex);\n\n uint256 multiplier = _getMultiplier(userStakingInfo[_msgSender()][stakeIndex].duration);\n\n uint256 currentWeightedStake = (amount * multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake -= currentWeightedStake;\n\n totalStaked -= amount;\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount -= amount;\n\n // check whether account is eligible for benefit from the protocol\n if (\n userStakingInfo[_msgSender()][stakeIndex].duration >= stakeDurationForPerks &&\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount < stakeAmountForPerks\n ) {\n highTierAccounts[_msgSender()] = false;\n }\n\n // remove staking info from array on full withdrawal\n if (userStakingInfo[_msgSender()][stakeIndex].stakedAmount == 0) {\n _claimReward(_msgSender(), stakeIndex);\n\n userStakingInfo[_msgSender()][stakeIndex] = userStakingInfo[_msgSender()][\n userStakingInfo[_msgSender()].length - 1\n ];\n userStakingInfo[_msgSender()].pop();\n }\n stakeRewardToken.safeTransfer(_msgSender(), amount);\n\n emit Unstaked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Claim pending rewards.\n * @dev Emits a `RewardPaid` event upon successful reward claim.\n * @param stakeIndex The index of user staking pool.\n */\n function getReward(uint256 stakeIndex) external nonReentrant notBlacklisted(_msgSender()) {\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n _updateReward(_msgSender(), stakeIndex);\n _claimReward(_msgSender(), stakeIndex);\n }\n\n // --------------------\n // ADMIN CONFIGURATION\n // --------------------\n\n /**\n * @notice Update Rewards Duration.\n * @dev Only callable by owner, and setting available only after rewards period.\n * @param duration New reward duration in seconds.\n */\n function setRewardsDuration(uint256 duration) external onlyOwner {\n require(finishAt < block.timestamp, \"reward duration is not finished\");\n rewardsDuration = duration;\n }\n\n /**\n * @notice Update stakeDurationForPerks\n * @dev Only callable by owner.\n * @param stakeDurationForPerks_ New stakeDurationForPerks.\n */\n function setStakeDurationForPerks(uint256 stakeDurationForPerks_) external onlyOwner {\n stakeDurationForPerks = stakeDurationForPerks_;\n }\n\n /**\n * @notice Update stakeAmountForPerks\n * @dev Only callable by owner.\n * @param stakeAmountForPerks_ New stakeDurationForPerks.\n */\n function setStakeAmountForPerks(uint256 stakeAmountForPerks_) external onlyOwner {\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n /**\n * @notice Push stakeDurationInfo\n * @dev Only callable by owner.\n */\n function pushStakeDurationInfo(StakeDurationInfo memory durationInfo) external onlyOwner {\n stakeDurationInfos.push(durationInfo);\n }\n\n /**\n * @notice Notify the contract about the amount of rewards to be distributed and update reward parameters.\n * @dev Only callable by owner.\n * @param amount The amount of reward to be distributed.\n */\n function notifyRewardAmount(uint256 amount) external onlyOwner {\n require(rewardsDuration > 0, \"rewards duration is not set\");\n require(amount > 0, \"amount = 0\");\n\n _updateReward(address(0), 0);\n\n if (block.timestamp >= finishAt) {\n rewardRatePerSec = amount / rewardsDuration;\n } else {\n uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatePerSec;\n rewardRatePerSec = (amount + remainingRewards) / rewardsDuration;\n }\n\n require(rewardRatePerSec > 0, \"reward rate = 0\");\n require(\n rewardRatePerSec <=\n (stakeRewardToken.balanceOf(address(this)) + amount - totalStaked) /\n rewardsDuration,\n \"reward amount > balance\"\n );\n\n finishAt = block.timestamp + rewardsDuration;\n lastUpdateTime = block.timestamp;\n\n totalRewards += amount;\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit NotifiedRewardAmount(amount, rewardRatePerSec);\n }\n\n // --------------------\n // VIEW FUNCTIONS\n // --------------------\n\n /**\n * @notice Get the last time when rewards were applicable for the specified reward token.\n * @return Timestamp of the most recent rewards calculation.\n */\n function lastTimeRewardApplicable() public view returns (uint256) {\n return _min(finishAt, block.timestamp);\n }\n\n /**\n * @notice Calculate the reward per token for a given reward token.\n * @return Current reward per token.\n */\n function rewardPerToken() public view returns (uint256) {\n if (totalStaked == 0) {\n return rewardPerTokenStored;\n }\n\n return\n rewardPerTokenStored +\n ((rewardRatePerSec * (lastTimeRewardApplicable() - lastUpdateTime) * 1e18) /\n totalWeightedStake);\n }\n\n /**\n * @notice Calculate the user's stake pool earnings\n * @param account Address of the user.\n * @param stakeIndex Index of the stakePool\n * @return Return earned amounts\n */\n function earned(address account, uint256 stakeIndex) public view returns (uint256) {\n StakingInfo memory userInfo = userStakingInfo[account][stakeIndex];\n uint256 multiplier = _getMultiplier(userInfo.duration);\n uint256 weightedAmount = (userInfo.stakedAmount * multiplier) / MULTIPLIER_BASIS;\n uint256 rewardsSinceLastUpdate = ((weightedAmount *\n (rewardPerToken() - userInfo.rewardPerTokenPaid)) / 1e18);\n return rewardsSinceLastUpdate + userInfo.rewards;\n }\n\n /**\n * @notice Get the earned rewards array for a user.\n * @param account Address of the user.\n * @return Return earned rewards array for a user.\n */\n function getEarnedUser(address account) public view returns (uint256[] memory) {\n uint256 numberOfPools = userStakingInfo[account].length;\n uint256[] memory earnedArray = new uint256[](numberOfPools);\n for (uint256 index; index < numberOfPools; index++) {\n earnedArray[index] = earned(account, index);\n }\n return earnedArray;\n }\n\n /**\n * @dev tierOf() function that always return that the given account is not\n * elligible to any LDY staking tier, except if the account is in the\n * highTierAccounts mapping.\n * @param account The account to check the tier of.\n */\n function tierOf(address account) public view returns (uint256 tier) {\n if (highTierAccounts[account]) return 3;\n return 0;\n }\n\n /**\n * @notice Get User Stake Data.\n * @param account The address of user.\n * @return StakingInfo array.\n */\n function getUserStakes(address account) external view returns (StakingInfo[] memory) {\n return userStakingInfo[account];\n }\n\n /**\n * @notice Get StakeDurationInfo.\n * @param index Index of StakeDurationInfos.\n * @return StakeDurationInfo.\n */\n function getStakeDurationInfo(uint256 index) external view returns (StakeDurationInfo memory) {\n require(stakeDurationInfos.length - 1 >= index, \"wrong index\");\n return stakeDurationInfos[index];\n }\n\n /**\n * @notice Send rewards to user.\n * @dev This is private function, called by getReward function.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _claimReward(address account, uint256 stakeIndex) private {\n uint256 reward = userStakingInfo[account][stakeIndex].rewards;\n\n if (reward > 0) {\n userStakingInfo[account][stakeIndex].rewards = 0;\n totalRewards -= reward;\n stakeRewardToken.safeTransfer(account, reward);\n emit RewardPaid(account, stakeIndex, reward);\n }\n }\n\n /**\n * @notice Calculate and update user rewards per stakeIndex.\n * @dev this is private function, called by stake, unstake, getRewards, and notifyRewardAmount functions.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _updateReward(address account, uint256 stakeIndex) private {\n rewardPerTokenStored = rewardPerToken();\n lastUpdateTime = lastTimeRewardApplicable();\n\n if (account != address(0)) {\n userStakingInfo[account][stakeIndex].rewards = earned(account, stakeIndex);\n userStakingInfo[account][stakeIndex].rewardPerTokenPaid = rewardPerTokenStored;\n }\n }\n\n /**\n * @notice Get multiplier from stakeDurationInfo based on duration\n * @param duration Stake Duration\n */\n function _getMultiplier(uint256 duration) private view returns (uint256) {\n uint256 stakeDurationInfosLength = stakeDurationInfos.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[i];\n if (duration == stakeDurationInfo.duration) {\n return stakeDurationInfo.multiplier;\n }\n }\n return 0;\n }\n\n /**\n * @notice Take minimum value between x and y.\n */\n function _min(uint256 x, uint256 y) private pure returns (uint256) {\n return x <= y ? x : y;\n }\n}\n" + }, + "contracts/src/libs/APRHistory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n/**\n * @title APRHistory\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This library offers utilities to efficiently maintain the history of an\n * on-chain APR (Annual Percentage Rate) state. Each entry in this history is called\n * a \"checkpoint\".\n *\n * @dev Intuition:\n * Each checkpoint in an APR history consists of two data:\n * - the creation timestamp\n * - the APR at that time\n *\n * Given that reading and writing to storage slots are among the most costly operations\n * in Solidity, this library provides a way to store those data in a way that minimizes\n * the number of used storage slots.\n *\n * Instead of storing each checkpoint in a separate storage slot, this library\n * facilitates the packing of up to 4 checkpoints in a single storage slot.\n *\n * @dev Definitions:\n * - Checkpoint: A record of an APR change\n * - Pack: A collection of 4 checkpoints stored in a single storage slot\n * - History: A dynamic array of packs\n * - Reference: A storage pointer to a checkpoint in the APR history\n * - CheckpointData: An in-memory representation of a checkpoint data\n *\n * @dev Value limitation:\n * This library can accommodate APRs only up to 65.536%. This is however sufficient for\n * APR in LToken contract, which is expected to remain below 10%.\n *\n * @dev For further details, see \"APRHistory\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary APRHistory {\n /**\n * @notice Represents data of a checkpoint extracted from the on-chain history.\n * For on-chain representation see \"Pack\" struct.\n * @param aprUD7x3 APR in UD7x3 format (e.g., 12345 = 12.345%).\n * @param timestamp Timestamp of the checkpoint's creation.\n */\n struct CheckpointData {\n uint16 aprUD7x3; // Allows up to 65.536%\n uint40 timestamp; // Supports dates up to 20/02/36812\n }\n\n /**\n * @notice Represents how APR checkpoints are stored on chain. Each pack can contain\n * the data 4 checkpoints. Packs are then stored in a dynamic array (the history).\n * @param aprsUD7x3 Array of checkpoints' APRs.\n * @param timestamps Array of checkpoints' timestamps.\n * @param cursor Index of the next checkpoint to be written.\n */\n struct Pack {\n uint16[4] aprsUD7x3;\n uint40[4] timestamps;\n uint32 cursor;\n }\n\n /**\n * @notice Represents a storage pointer to a specific checkpoint in the history.\n * @param packIndex Index of the pack the checkpoint belongs to.\n * @param cursorIndex Index of the checkpoint in this pack (between 0 and 3).\n */\n struct Reference {\n uint256 packIndex;\n uint32 cursorIndex;\n }\n\n /**\n * @notice Compares two checkpoints references.\n * @param ref1 The first reference to compare.\n * @param ref2 The second reference to compare.\n * @return Whether the two references points to the same checkpoint.\n */\n function eq(Reference memory ref1, Reference memory ref2) external pure returns (bool) {\n return ref1.packIndex == ref2.packIndex && ref1.cursorIndex == ref2.cursorIndex;\n }\n\n /**\n * @notice Returns the reference of the checkpoint that should come right after the\n * referenced checkpoint in the APR history.\n * @param ref The reference to be incremented.\n * @return The incremented reference.\n */\n function incrementReference(Reference memory ref) public pure returns (Reference memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L1\");\n\n // If the given ref is the last slot in its pack, return ref of next pack's first slot\n if (ref.cursorIndex == 3) return Reference(ref.packIndex + 1, 0);\n //\n // Else, return ref of next slot in current pack\n else return Reference(ref.packIndex, ref.cursorIndex + 1);\n }\n\n /**\n * @notice Extracts checkpoint data from a given reference and in APR history.\n * @param self The APR history to extract the checkpoint from.\n * @param ref The reference of the checkpoint data to extract.\n * @return The extracted checkpoint's data.\n */\n function getDataFromReference(\n Pack[] storage self,\n Reference memory ref\n ) public view returns (CheckpointData memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L2\");\n\n // Ensure pack index of the given ref exists in history\n require(ref.packIndex < self.length, \"L3\");\n\n // Retrieve pack data from history\n Pack memory pack = self[ref.packIndex];\n\n // Ensure cursor index of the given ref has been written\n require(ref.cursorIndex < pack.cursor, \"L4\");\n\n // Build and return the checkpoint data\n return\n CheckpointData({\n aprUD7x3: pack.aprsUD7x3[ref.cursorIndex],\n timestamp: pack.timestamps[ref.cursorIndex]\n });\n }\n\n /**\n * @notice Retrieves the reference to the most recently added checkpoint in the APR history.\n * @param self The history to extract the reference from.\n * @return The reference of the latest checkpoint.\n */\n function getLatestReference(Pack[] storage self) public view returns (Reference memory) {\n // Ensure the given history is not empty\n require(self.length != 0, \"L5\");\n\n // Retrieve latest pack's index and cursor\n uint256 packIndex = self.length - 1;\n uint32 packCursor = self[packIndex].cursor;\n\n // If this is the first pack ever, ensure it is not empty\n if (packIndex == 0) require(packCursor != 0, \"L6\");\n\n // If the pack is empty, return ref of previous pack's latest slot\n if (packCursor == 0) return Reference(packIndex - 1, 3);\n //\n // Else, return ref of previous slot in current pack\n else return Reference(packIndex, packCursor - 1);\n }\n\n /**\n * @notice Appends a new empty pack to the end of the given APR history array.\n * @param self The APR history to append an empty to.\n */\n function newBlankPack(Pack[] storage self) internal {\n // If history is not empty, ensure the latest pack is full\n require(self.length == 0 || getLatestReference(self).cursorIndex == 3, \"L7\");\n\n // Push a new blank pack to the history array\n self.push(\n Pack({\n aprsUD7x3: [uint16(0), uint16(0), uint16(0), uint16(0)],\n timestamps: [uint40(0), uint40(0), uint40(0), uint40(0)],\n cursor: 0\n })\n );\n }\n\n /**\n * @notice Write a new APR checkpoint at the end of the given history array.\n * @param self The array of packs to write the new checkpoint to.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(Pack[] storage self, uint16 aprUD7x3) external {\n // Determine the reference where the new checkpoint should be written\n Reference memory newRef = self.length == 0\n ? Reference(0, 0)\n : incrementReference(getLatestReference(self));\n\n // If pack to be written doesn't exist yet, push a new blank pack in history\n if (newRef.packIndex >= self.length) newBlankPack(self);\n\n // Retrieve the pack where the new checkpoint will be stored\n Pack memory pack = self[newRef.packIndex];\n\n // Add new checkpoint's data to the pack\n pack.aprsUD7x3[newRef.cursorIndex] = aprUD7x3;\n pack.timestamps[newRef.cursorIndex] = uint40(block.timestamp);\n\n // Increment the pack's cursor\n pack.cursor++;\n\n // Write the updated pack in storage\n self[newRef.packIndex] = pack;\n }\n\n /**\n * @notice Retrieves the APR of the latest checkpoint written in the APR history.\n * @param self The history array to read APR from.\n * @return The latest checkpoint's APR.\n */\n function getAPR(Pack[] storage self) public view returns (uint16) {\n // Retrieve the latest checkpoint data\n Reference memory ref = getLatestReference(self);\n CheckpointData memory data = getDataFromReference(self, ref);\n\n // Return the latest checkpoint's APR\n return data.aprUD7x3;\n }\n}\n" + }, + "contracts/src/libs/SUD.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title SUD\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice SUD serves as an intermediary number format for calculations within this\n * codebase. It ensures consistency and reduces precision losses. This library\n * facilitates conversions between various number formats and the SUD format.\n *\n * @dev Intuition:\n * This codebase employs the UD (unsigned decimal fixed-point numbers) format to\n * represent both percentage rates and tokens amounts.\n *\n * Rates are expressed in UD7x3 format, whereas the format for tokens amounts depends on\n * the decimals() value of the involved tokens.\n *\n * Three challenges arise from this:\n * 1) To compute values together, it's essential that they are in the same format\n * 2) Calculations involving consecutive divisions on UD numbers lead to accumulated\n * precision loss (because division shrinks). A common approach is to scale up and\n * down values by a few decimals before and after performing calculations.\n * 3) Given that rates use the UD7x3 format, if we decided to scale them to and from\n * the number of decimals of the involved token, 1 to 3 of the rates' decimals would\n * be shrunk in case token's decimals number is in [0, 2].\n *\n * To address these challenges, this library provides the SUD format, which acts as a\n * consistent and scaled intermediate format to perform calculations.\n *\n * SUD is an acronym for either \"Scaled UD\" or \"Safe UD\".\n *\n * @dev Definitions:\n * - Integer: A number without fractional part, e.g., block.timestamp\n * - UD: A decimal unsigned fixed-point number. The \"UD\" notation is inspired from\n * libraries like [prb-math](https://github.com/PaulRBerg/prb-math/)\n * - Amount: A token amount. A UD with an unknown repartition of digits between integral\n * and fractional parts (as token amounts have variable decimal numbers)\n * - Rate: A percentage rate. An UD with 7 integral digits and 3 fractional ones (= UD7x3)\n * - SUD: An intermediate format to perform calculations involving Rates and Amounts. A UD\n * with 3 more decimals than the involved UD with the highest decimals number. As\n * rates are represented by UD7x3, a SUD number has at least 6 decimals (3+3) and\n * so ranges from UD71x6 to UD0x77 formats.\n *\n * @dev A conversion library:\n * This library provides utilities to perform the following conversions:\n * - Amount <--> SUD\n * - Rate (UD7x3) <--> SUD\n * - Integer <--> SUD\n *\n * @dev Why scaling by 3 decimals?\n * - It provides an adequate degree of precision for this codebase,\n * - It enables the conversion of a UD7x3 rate to SUD format by merely scaling it up by\n * the involved token's decimal number, so is gas efficient.\n *\n * @dev Why internal functions?\n * The functions of this library are not set to external because incorporating them\n * directly into contracts is more gas-efficient. Given their minimal size and frequent\n * usage in the InvestUpgradeable, LDYStaking, and LToken contracts, any bytecode savings\n * from making them external are negated by the additional bytecode required for external\n * calls to this library. This can be observed by comparing the output of `bun cc:size`\n * when those functions's visibility is set to external or internal.\n *\n * @dev Precision warning:\n * While this library mitigates precision loss during calculations on UD numbers, it's\n * important to note that tokens with lower decimal counts and supply inherently suffer\n * more from precision loss. Conversely, tokens with higher decimal counts and supply\n * will experience less precision loss.\n *\n * @dev For further details, see \"SUD\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary SUD {\n /**\n * @notice Retrieves decimals number of the given ERC20 contract address.\n * @param tokenAddress The address to retrieve decimals number from.\n * @return decimals The decimals number of the given ERC20 contract address.\n */\n function decimalsOf(address tokenAddress) internal view returns (uint256 decimals) {\n return IERC20MetadataUpgradeable(tokenAddress).decimals();\n }\n\n /**\n * @notice Convert a given token amount into SUD format.\n * @param nAmount The token amount to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The amount in SUD format\n */\n function fromAmount(uint256 nAmount, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nAmount * 10 ** (6 - decimals);\n\n // Else return a number with decimals+3 fractional digits\n return nAmount * 10 ** 3;\n }\n\n /**\n * @notice Convert a given SUD number into token amount format.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nAmount The number in amount format\n */\n function toAmount(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nAmount) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** (6 - decimals);\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** 3;\n }\n\n /**\n * @notice Converts a given UD7x3 rate into SUD format.\n * @param nUD7x3 The UD7x3 rate to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The rate in SUD format.\n */\n function fromRate(uint256 nUD7x3, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nUD7x3 * 10 ** 3;\n\n // Else, return a number with decimals+3 fractional digits\n return nUD7x3 * 10 ** decimals;\n }\n\n /**\n * @notice Converts a given SUD number into a UD7x3 rate.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nUD7x3 The number in UD7x3 rate format.\n */\n function toRate(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nUD7x3) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 3;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** decimals;\n }\n\n /**\n * @notice Converts a given integer into SUD format.\n * @param n The integer to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The integer in SUD format.\n */\n function fromInt(uint256 n, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return n * 10 ** 6;\n\n // Else, return a number with decimals+3 fractional digits\n return n * 10 ** (decimals + 3);\n }\n\n /**\n * @notice Converts a given SUD number as an integer (all decimals shrinked).\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return n The SUD number as an integer.\n */\n function toInt(uint256 nSUD, uint256 decimals) internal pure returns (uint256 n) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 6;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** (decimals + 3);\n }\n}\n" + }, + "contracts/src/LToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ERC20WrapperUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\";\nimport \"./abstracts/base/ERC20BaseUpgradeable.sol\";\nimport {InvestUpgradeable} from \"./abstracts/InvestUpgradeable.sol\";\nimport {LDYStaking} from \"./LDYStaking.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {SUD} from \"./libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {ITransfersListener} from \"./interfaces/ITransfersListener.sol\";\n\n/**\n * @title LToken\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e.,\n * investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin.\n * As soon as a wallet holds some L-Tokens, it starts receiving rewards in\n * the form of additional L-Tokens, which are auto-compounded over time.\n *\n * @dev Definitions:\n * - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio).\n * - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees).\n * - Instant: Processed immediately.\n * - Request: Queued for later processing.\n * - Big Request: A requested withdrawal exceeding half of the retention rate.\n * - (Withdrawal) queue: A list of all requested withdrawals sorted by priority.\n * - Request ID: The index of a withdrawal request in the queue array.\n * - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain.\n * - Fees Rate: Percentage of fees applied to successful withdrawals.\n * - Usable underlyings: Amount of underlying tokens that have been deposited through\n * expected ways and are so considered safe to use by the contract.\n * - Transfers listeners: External contracts listening on L-Tokens transfers.\n * - Fund wallet: Wallet managed by the Ledgity's financial team.\n * - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request\n * processing.\n *\n * Note that words between parenthesis are sometimes omitted for brevity.\n *\n * @dev Deployment notice:\n * This contract can safely receive funds immediately after initialization. (i.e., there\n * is no way for funds to be sent to non-owned addresses). It is, however, recommended to\n * replace ASAP owner and fund wallets with multi-sig wallets.\n *\n * @dev For further details, see \"LToken\" section of whitepaper.\n * @custom:oz-upgrades-unsafe-allow external-library-linking\n * @custom:security-contact security@ledgity.com\n */\ncontract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @dev Represents type of actions triggering ActivityEvent events.\n enum Action {\n Deposit,\n Withdraw\n }\n\n /// @dev Represents different status of actions triggering ActivityEvent events.\n enum Status {\n Queued,\n Cancelled,\n Success,\n Moved\n }\n\n /**\n * @notice Represents a withdrawal request in the queue.\n * @dev A request fits in a single storage slot (32 bytes).\n * @param account The account that initiated the request.\n * @param amount The amount of underlying tokens requested.\n */\n struct WithdrawalRequest {\n address account; // 20 bytes\n uint96 amount; // 12 bytes\n }\n\n /// @notice Upper limit of retention rate.\n uint32 private constant MAX_RETENTION_RATE_UD7x3 = 10 * 10 ** 3; // 10%\n\n /// @notice Upper limit of fees rate.\n uint32 private constant MAX_FEES_RATE_UD7x3 = 20 * 10 ** 3; // 20%\n\n /// @notice Used in activity events to represent the absence of request ID.\n int256 private constant NO_ID = -1;\n\n /// @notice Holds a reference to the LDYStaking contract.\n LDYStaking public ldyStaking;\n\n /// @notice Holds address of withdrawer wallet (managed by withdrawal server).\n address payable public withdrawer;\n\n /// @notice Holds address of fund wallet (managed by Ledgity financial team).\n address public fund;\n\n /// @notice Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\n uint32 public feesRateUD7x3;\n\n /// @notice Holds the retention rate in UD7x3 format.\n uint32 public retentionRateUD7x3;\n\n /// @notice Holds the amount of withdrawal fees not yet claimed by contract's owner.\n uint256 public unclaimedFees;\n\n /// @notice Holds the amount of L-Tokens currently in the withdrawal queue.\n uint256 public totalQueued;\n\n /**\n * @notice Holds the amount of underlying tokens considered as usable by the contract.\n * @dev Are usable, only underlying tokens deposit through deposit() or fund() functions.\n */\n uint256 public usableUnderlyings;\n\n /// @notice Holds an ordered list of active withdrawal requests.\n WithdrawalRequest[] public withdrawalQueue;\n\n /// @notice Holds the index of the next withdrawal request to process in the queue.\n uint256 public withdrawalQueueCursor;\n\n /**\n * @notice Holds a list of all currently frozen withdrawal requests.\n * @dev If a request emitter as been blacklisted, its request is moved here to prevent\n * it from blocking the queue.\n */\n WithdrawalRequest[] public frozenRequests;\n\n /**\n * @notice Holds a list of contracts' references that are listening to L-Tokens transfers.\n * @dev onLTokenTransfer() functions of those contracts will be called on each transfer.\n */\n ITransfersListener[] public transfersListeners;\n\n /**\n * @notice Emitted to inform listeners about a change in the contract's TVL.\n * @dev TVL = realTotalSupply()\n * @param newTVL The new TVL of the contract.\n */\n event TVLChangeEvent(uint256 newTVL);\n\n /**\n * @notice Emitted to inform listerners about an activity related to deposits and withdrawals.\n * @param id ID of the involved withdrawal request or NO_ID (-1) if not applicable.\n * @param account The account involved in the activity.\n * @param action The type of activity.\n * @param amount The amount of underlying tokens involved in the activity.\n * @param newStatus The new status of the activity.\n * @param newId The new ID of the request if it has been moved in the queue.\n */\n event ActivityEvent(\n int256 indexed id,\n address indexed account,\n Action indexed action,\n uint256 amount,\n uint256 amountAfterFees,\n Status newStatus,\n int256 newId\n );\n\n /**\n * @notice Emitted to inform listeners that some rewards have been minted.\n * @param account The account that received the rewards.\n * @param balanceBefore The balance of the account before the minting.\n * @param rewards The amount of minted rewards.\n */\n event MintedRewardsEvent(address indexed account, uint256 balanceBefore, uint256 rewards);\n\n /// @notice Reverts if the function caller is not the withdrawer wallet.\n modifier onlyWithdrawer() {\n require(_msgSender() == withdrawer, \"L39\");\n _;\n }\n\n /// @notice Reverts if the function caller is not the fund wallet.\n modifier onlyFund() {\n require(_msgSender() == fund, \"L40\");\n _;\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param underlyingToken The address of the underlying stablecoin ERC20 token.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address ldyStaking_,\n address underlyingToken\n ) public initializer {\n // Initialize ERC20 base.\n string memory underlyingSymbol = IERC20MetadataUpgradeable(underlyingToken).symbol();\n __ERC20Base_init(\n globalOwner_,\n globalPause_,\n globalBlacklist_,\n string(abi.encodePacked(\"Ledgity \", underlyingSymbol)),\n string(abi.encodePacked(\"L\", underlyingSymbol))\n );\n\n // IMPORTANT: Below calls must not be restricted to owner at any point.\n // This is because the GlobalOwner contract may not be a fresh one, and so\n // the contract deployer may not be the owner anymore after ERC20Base init.\n\n // Initialize other parents contracts.\n __ERC20Wrapper_init(IERC20Upgradeable(underlyingToken));\n __Invest_init_unchained(address(this));\n\n // Set LDYStaking contract\n ldyStaking = LDYStaking(ldyStaking_);\n\n // Set initial withdrawal fees rate to 0.3%\n feesRateUD7x3 = 300;\n\n // Set initial retention rate to 10%\n retentionRateUD7x3 = 10_000;\n\n // Default withdrawer and fund wallet to contract owner address. This prevents\n // any loss of funds if a deposit/withdrawal is made before those are manually set.\n withdrawer = payable(owner());\n fund = payable(owner());\n }\n\n /**\n * @notice Required override of decimals() which is implemented by both\n * ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\n * @dev The ERC20WrapperUpgradeable version is preferred because it mirrors the\n * decimals amount of the underlying stablecoin token.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function decimals()\n public\n view\n override(ERC20Upgradeable, ERC20WrapperUpgradeable)\n returns (uint8)\n {\n return ERC20WrapperUpgradeable.decimals();\n }\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\n * @dev Both version are the same as ERC20BaseUpgradeable.paused() mirrors\n * GlobalPausableUpgradeable.paused(), so a random one is chosen.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, ERC20BaseUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @notice Updates the current withdrawal fee rate.\n * @param feesRateUD7x3_ The new withdrawal fee rate in UD7x3 format.\n */\n function setFeesRate(uint32 feesRateUD7x3_) public onlyOwner {\n require(feesRateUD7x3_ <= MAX_FEES_RATE_UD7x3, \"L88\");\n feesRateUD7x3 = feesRateUD7x3_;\n }\n\n /**\n * @notice Updates the current underlying token retention rate.\n * @dev The retention rate is capped at 10%, which ensures that no more than 10% of\n * deposited assets will ever be exposed in this contract (reduces attack surface).\n * @param retentionRateUD7x3_ The new retention rate in UD7x3 format.\n */\n function setRetentionRate(uint32 retentionRateUD7x3_) public onlyOwner {\n require(retentionRateUD7x3_ <= MAX_RETENTION_RATE_UD7x3, \"L41\");\n retentionRateUD7x3 = retentionRateUD7x3_;\n }\n\n /**\n * @notice Updates the address of LDYStaking contract.\n * @param ldyStakingAddress The address of the new LDYStaking contract.\n */\n function setLDYStaking(address ldyStakingAddress) public onlyOwner {\n ldyStaking = LDYStaking(ldyStakingAddress);\n }\n\n /**\n * @notice Updates the address of the withdrawer wallet.\n * @param withdrawer_ The address of the new withdrawer wallet.\n */\n function setWithdrawer(address payable withdrawer_) public onlyOwner {\n // Ensure address is not the zero address (pre-processing fees would be lost else)\n require(withdrawer_ != address(0), \"L63\");\n\n // Set new withdrawer wallet's address\n withdrawer = withdrawer_;\n }\n\n /**\n * @notice Updates the address of the fund wallet.\n * @param fund_ The address of the new fund wallet.\n */\n function setFund(address payable fund_) public onlyOwner {\n // Ensure address is not the zero address (deposited tokens would be lost else)\n require(fund_ != address(0), \"L64\");\n\n // Set new fund wallet's address\n fund = fund_;\n }\n\n /**\n * @notice Adds a new contract to the L-Token transfers list.\n * @dev Each time a transfer occurs, the onLTokenTransfer() function of the\n * specified contract will be called.\n * @dev IMPORTANT SECURITY NOTE: This method is not intended to be used with\n * contracts that are not owned by the Ledgity team.\n * @param listenerContract The address of the new transfers listener contract.\n */\n function listenToTransfers(address listenerContract) public onlyOwner {\n transfersListeners.push(ITransfersListener(listenerContract));\n }\n\n /**\n * @notice Removes a contract from the L-Token transfers list.\n * @dev The onLTokenTransfer() function of the specified contract will not be called\n * anymore each time a L-Token transfer occurs.\n * @param listenerContract The address of the listener contract.\n */\n function unlistenToTransfers(address listenerContract) public onlyOwner {\n // Find index of listener contract in transferListeners array\n int256 index = -1;\n uint256 transfersListenersLength = transfersListeners.length;\n for (uint256 i = 0; i < transfersListenersLength; i++) {\n if (address(transfersListeners[i]) == listenerContract) {\n index = int256(i);\n break;\n }\n }\n\n // Revert if given contract wasn't listening to transfers\n require(index > -1, \"L42\");\n\n // Else, remove transfers listener contract from listeners array\n transfersListeners[uint256(index)] = transfersListeners[transfersListenersLength - 1];\n transfersListeners.pop();\n }\n\n /**\n * @notice Retrieves the amount of given account's not yet minted rewards.\n * @dev This is a public implementation of InvestUpgradeable_rewardsOf(). In the\n * context of LToken, this function returns the amount of rewards that have not been\n * distributed/minted yet to the specified account.\n * @dev This is particularly useful for off-chain services to display charts and\n * statistics, as seen in the Ledgity Yield's frontend.\n * @param account The account to check the unminted rewards of.\n * @return The amount of account's unminted rewards.\n */\n function unmintedRewardsOf(address account) public view returns (uint256) {\n return _rewardsOf(account, true);\n }\n\n /**\n * @notice Retrieves the \"real\" balance of an account, i.e., excluding its not yet\n * minted/distributed rewards.\n * @param account The account to check the real balance of.\n * @return The real balance of the account.\n */\n function realBalanceOf(address account) public view returns (uint256) {\n return super.balanceOf(account);\n }\n\n /**\n * @notice Retrieves the total balance of L-Tokens that belong to the account.\n * @dev This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have\n * not been yet minted to the specified account.\n * @param account The account to check the total balance of.\n * @return The total balance of the account.\n */\n function balanceOf(address account) public view override returns (uint256) {\n return realBalanceOf(account) + unmintedRewardsOf(account);\n }\n\n /**\n * @notice Returns the \"real\" amount of existing L-Tokens, i.e., excluding not yet\n * minted withdrawal fees and L-Tokens currently in the withdrawal queue.\n * @return The real total supply of L-Tokens.\n */\n function realTotalSupply() public view returns (uint256) {\n return super.totalSupply();\n }\n\n /**\n * @notice Retrives the total supply of L-Tokens, including not yet minted withdrawal\n * fees and L-Tokens currently in the withdrawal queue.\n * @return The total supply of L-Tokens.\n */\n function totalSupply() public view override returns (uint256) {\n return realTotalSupply() + totalQueued + unclaimedFees;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address.\n * @dev This override of RecoverableUpgradeable.recoverERC20() prevents the recovered\n * token from being the underlying token.\n * @inheritdoc RecoverableUpgradeable\n */\n function recoverERC20(address tokenAddress, uint256 amount) public override onlyOwner {\n // Ensure the token is not the underlying token\n require(tokenAddress != address(underlying()), \"L43\");\n\n // Proceed to recovery\n super.recoverERC20(tokenAddress, amount);\n }\n\n /**\n * @notice Recovers underlying tokens accidentally sent to the contract.\n * @dev To prevent owner from being able to drain the contract, this function only\n * allows recovering \"unusable\" underlying tokens, i.e., tokens that have not been\n * sent through fund() or deposit() functions.\n */\n function recoverUnderlying() external onlyOwner {\n // Compute the recoverable amount by taking the difference between the contract's\n // balance and the amount of usable underlying tokens\n uint256 recoverableAmount = underlying().balanceOf(address(this)) - usableUnderlyings;\n\n // Revert if there is nothing to recover\n require(recoverableAmount > 0, \"L44\");\n\n // Else, proceed to underlying tokens recovery\n super.recoverERC20(address(underlying()), recoverableAmount);\n }\n\n /**\n * @notice Retrieves the amount of underlying tokens invested by the given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract. In\n * LToken contract, the investment of an account is equal to its real balance.\n * @inheritdoc InvestUpgradeable\n */\n function _investmentOf(address account) internal view override returns (uint256) {\n return realBalanceOf(account);\n }\n\n /**\n * @notice Distributes a specified amount of rewards (in L-Tokens) to a given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract so\n * it can distribute rewards to accounts before each period reset.\n * @dev InvestUpgradeable contract already ensure that amount > 0.\n * @inheritdoc InvestUpgradeable\n */\n function _distributeRewards(address account, uint256 amount) internal override returns (bool) {\n // Inform listeners of the rewards minting\n emit MintedRewardsEvent(account, realBalanceOf(account), amount);\n\n // Mint L-Tokens rewards to account\n _mint(account, amount);\n\n // Return true indicating to InvestUpgradeable that the rewards have been distributed\n return true;\n }\n\n /**\n * @notice Override of ERC20._beforeTokenTransfer() to integrate with InvestUpgradeable.\n * @dev This overriden version ensure that _beforeInvestmentChange() hook is properly\n * called each time an account's balance is going to change.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already included in ERC20BaseUpgradeable._beforeTokenTransfer().\n * @inheritdoc ERC20BaseUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20Upgradeable, ERC20BaseUpgradeable) {\n ERC20BaseUpgradeable._beforeTokenTransfer(from, to, amount);\n\n // Invoke _beforeInvestmentChange() hook for non-zero accounts\n if (from != address(0)) _beforeInvestmentChange(from, true);\n if (to != address(0)) _beforeInvestmentChange(to, true);\n }\n\n /**\n * @notice Override of ERC20._afterTokenTransfer() to notify all transfers listeners.\n * @dev This overriden version will trigger onLTokenTransfer() functions of all\n * transfers listeners.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already checked in _beforeTokenTransfer().\n * @inheritdoc ERC20Upgradeable\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\n super._afterTokenTransfer(from, to, amount);\n\n // If some L-Token have been burned/minted, inform listeners of a TVL change\n if (from == address(0) || to == address(0)) emit TVLChangeEvent(totalSupply());\n\n // Trigger onLTokenTransfer() functions of all the transfers listeners\n for (uint256 i = 0; i < transfersListeners.length; i++) {\n transfersListeners[i].onLTokenTransfer(from, to, amount);\n }\n }\n\n /**\n * @notice Computes the maximum amount of underlying tokens that should be retained\n * by the contract (based on retention rate).\n * @return amount The expected amount of retained underlying tokens.\n */\n function getExpectedRetained() public view returns (uint256 amount) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert totalSupply and retentionRate to SUD\n uint256 totalSupplySUD = SUD.fromAmount(totalSupply(), d);\n uint256 retentionRateSUD = SUD.fromRate(retentionRateUD7x3, d);\n\n // Compute and return expected retained amount\n uint256 expectedRetainedSUD = (totalSupplySUD * retentionRateSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(expectedRetainedSUD, d);\n }\n\n /// @notice Transfers underlying tokens exceeding the retention rate to the fund wallet.\n function _transferExceedingToFund() internal {\n // Retrieve the expected amount retained\n uint256 expectedRetained = getExpectedRetained();\n\n // If usable underlyings are less than or equal to expected retained, return\n if (usableUnderlyings <= expectedRetained) return;\n\n // Else, exceeding amount is equal to difference between those values\n uint256 exceedingAmount = usableUnderlyings - expectedRetained;\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= exceedingAmount;\n\n // Transfer the exceeding amount to the fund wallet\n underlying().safeTransfer(fund, exceedingAmount);\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.withdrawTo() that reverts.\n * Use instantWithdrawal() or requestWithdrawal() functions instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function withdrawTo(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L45\");\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.depositFor() that reverts.\n * Use deposit() function instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function depositFor(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L46\");\n }\n\n /**\n * @notice Allows exchanging some underlying tokens for the same amount of L-Tokens.\n * @param amount The amount of underlying tokens to deposit.\n */\n function deposit(uint256 amount) public whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough underlying tokens to deposit\n require(underlying().balanceOf(_msgSender()) >= amount, \"L47\");\n\n // Update usable underlyings balance accordingly\n usableUnderlyings += amount;\n\n // Inform listeners of the deposit activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Deposit,\n amount,\n amount,\n Status.Success,\n NO_ID\n );\n\n // Receive underlying tokens and mint L-Tokens to the account in a 1:1 ratio\n super.depositFor(_msgSender(), amount);\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Computes fees and net withdrawn amount for a given account withdrawing a\n * given amount.\n * @param account The account initiating the withdrawal.\n * @param amount The amount of the withdrawal.\n */\n function getWithdrawnAmountAndFees(\n address account,\n uint256 amount\n ) public view returns (uint256 withdrawnAmount, uint256 fees) {\n // If the account is eligible to staking tier 2, no fees are applied\n if (ldyStaking.tierOf(account) >= 2) return (amount, 0);\n\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert amount and fees rate to SUD\n uint256 amountSUD = SUD.fromAmount(amount, d);\n uint256 feesRateSUD = SUD.fromRate(feesRateUD7x3, d);\n\n // Compute fees and withdrawn amount (initial amount minus fees)\n uint256 feesSUD = (amountSUD * feesRateSUD) / SUD.fromInt(100, d);\n fees = SUD.toAmount(feesSUD, d);\n withdrawnAmount = amount - fees;\n }\n\n /**\n * @notice Allows instaneously exchanging a given amount of L-Tokens for the same\n * amount of underlying tokens. It will fail if the contract currently doesn't hold\n * enough underlying tokens to cover the withdrawal.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestWithdrawal() function otherwise.\n * @param amount The amount L-Tokens to withdraw.\n */\n function instantWithdrawal(uint256 amount) external whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L48\");\n\n // Can the contract cover this withdrawal plus all already queued requests?\n bool cond1 = totalQueued + amount <= usableUnderlyings;\n\n // Is caller eligible to staking tier 2 and the contract can cover this withdrawal?\n bool cond2 = ldyStaking.tierOf(_msgSender()) >= 2 && amount <= usableUnderlyings;\n\n // Revert if conditions are not met for the withdrawal to be processed instantaneously\n if (!(cond1 || cond2)) revert(\"L49\");\n\n // Else, retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(_msgSender(), amount);\n\n // Increase unclaimed fees amount accordingly\n unclaimedFees += fees;\n\n // Decrease usable underlyings balance accordingly\n usableUnderlyings -= withdrawnAmount;\n\n // Inform listeners of this instant withdrawal activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Withdraw,\n amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Burn withdrawal fees from the account\n _burn(_msgSender(), fees);\n\n // Burn account's withdrawn L-Tokens and transfer to it underlying tokens in a 1:1 ratio\n super.withdrawTo(_msgSender(), withdrawnAmount);\n }\n\n /**\n * @notice Allows requesting the exchange of a given amount of L-Tokens for the same\n * amount of underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n * @param amount The amount L-Tokens to withdraw.\n */\n function requestWithdrawal(\n uint256 amount\n ) public payable whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L53\");\n\n // Ensure the requested amount doesn't overflow uint96\n require(amount <= type(uint96).max, \"L54\");\n\n // Ensure the sender attached the pre-paid processing gas fees\n require(msg.value == 0.003 * 10 ** 18, \"L55\");\n\n // Create withdrawal request data\n WithdrawalRequest memory request = WithdrawalRequest({\n account: _msgSender(),\n amount: uint96(amount)\n });\n\n // Will hold the request ID\n uint256 requestId;\n\n // Append request to the withdrawal queue:\n // - At the beginning, if account is eligible to staking tier 2 and cursor is not 0\n if (ldyStaking.tierOf(_msgSender()) >= 2 && withdrawalQueueCursor > 0) {\n withdrawalQueueCursor--;\n requestId = withdrawalQueueCursor;\n withdrawalQueue[requestId] = request;\n }\n // - At the end else\n else {\n withdrawalQueue.push(request);\n requestId = withdrawalQueue.length - 1;\n }\n\n // Increase total amount queued accordingly\n totalQueued += amount;\n\n // Inform listeners of this new queued withdrawal activity event\n emit ActivityEvent(\n int256(requestId),\n _msgSender(),\n Action.Withdraw,\n amount,\n amount,\n Status.Queued,\n NO_ID\n );\n\n // Burn withdrawal L-Tokens amount from account's balance\n _burn(_msgSender(), amount);\n\n // Forward pre-paid processing gas fees to the withdrawer wallet\n (bool sent, ) = withdrawer.call{value: msg.value}(\"\");\n require(sent, \"L56\");\n }\n\n /**\n * @notice Processes queued withdrawal requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n * @dev For further details, see \"LToken > Withdrawals\" section of whitepaper.\n */\n function processQueuedRequests() external onlyWithdrawer whenNotPaused {\n // Accumulators variables, will be written on-chain after the loop\n uint256 cumulatedFees = 0;\n uint256 cumulatedWithdrawnAmount = 0;\n uint256 nextRequestId = withdrawalQueueCursor;\n\n // Cache queue length to avoid multiple SLOADs and avoid infinite loop as big\n // requests are increasing the queue length when moved at the end of the queue.\n uint256 queueLength = withdrawalQueue.length;\n\n // Iterate over requests to be processed\n while (nextRequestId < queueLength) {\n // Stop processing requests if there is not enough gas left to continue the\n // loop and properly end the function call. This prevents an attacker from\n // blocking the withdrawal processing by creating a ton of tiny requests so\n // this function call cannot fit anymore in block gas limit.\n if (gasleft() < 45000) break;\n\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[nextRequestId];\n\n // Skip empty request (processed big requests or cancelled requests)\n if (request.account == address(0)) {}\n //\n // If account has been blacklisted since request emission\n else if (isBlacklisted(request.account)) {\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request in the frozen requests list\n frozenRequests.push(request);\n }\n //\n // Or if request is a big request, move it at the end of the queue for now.\n // This request will be processed manually later using processBigQueuedRequest()\n else if (request.amount > getExpectedRetained() / 2) {\n // Inform listeners of this queued request being moved at the end of the queue\n emit ActivityEvent(\n int256(nextRequestId),\n _msgSender(),\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Moved,\n int256(withdrawalQueue.length)\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request at the end of the queue\n withdrawalQueue.push(request);\n }\n //\n // Else, continue request processing\n else {\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Break if the contract doesn't hold enough funds to cover the request\n if (withdrawnAmount > usableUnderlyings - cumulatedWithdrawnAmount) break;\n\n // Accumulate fees and withdrawn amount\n cumulatedFees += fees;\n cumulatedWithdrawnAmount += withdrawnAmount;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(nextRequestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Transfer underlying tokens to account. Burning L-Tokens is not required\n // as equestWithdrawal() already did it.\n // Security note: Re-entrancy warning are disabled as the request has\n // just been deleted from the queue, it will so be skipped if trying to\n // process it again.\n // slither-disable-next-line reentrancy-no-eth\n underlying().safeTransfer(request.account, withdrawnAmount);\n }\n\n // Increment next request ID\n nextRequestId++;\n }\n\n // Increase unclaimed fees by the amount of cumulated fees\n unclaimedFees += cumulatedFees;\n\n // Decrease usable underlyings by the cumulated amount of withdrawn underlyings\n usableUnderlyings -= cumulatedWithdrawnAmount;\n\n // Decrease total amount queued by the cumulated amount requested\n totalQueued -= cumulatedWithdrawnAmount + cumulatedFees;\n\n // Update new queue cursor\n withdrawalQueueCursor = nextRequestId;\n\n // Retention rate cannot exceeds as the withdrawal decreases both usable\n // underlyings and expected retained amounts by the same number and as the\n // expected retained amount is a subset of usable underlyings amount.\n }\n\n /**\n * @notice Processes a given queued big withdrawal request (one that exceeds half of\n * the retention rate).\n * @dev In contrast to non-big requests processing, this function will uses to fund\n * wallet's balance to fill the request. This allows processing requests that are\n * greater than retention rate without having to exceed this rate on the contract.\n * @param requestId The ID of the big request to process.\n */\n function processBigQueuedRequest(uint256 requestId) external onlyFund whenNotPaused {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure the request is active\n require(request.account != address(0), \"L66\");\n\n // Ensure the request emitter has not been blacklisted since request emission\n require(!isBlacklisted(request.account), \"L50\");\n\n // Ensure this is indeed a big request\n require(request.amount > getExpectedRetained() / 2, \"L51\");\n\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Ensure withdrawn amount can be covered by contract + fund wallet balances\n uint256 fundBalance = underlying().balanceOf(fund);\n require(withdrawnAmount <= usableUnderlyings + fundBalance, \"L52\");\n\n // Increase amount of unclaimed fees accordingly\n unclaimedFees += fees;\n\n // Decrease total queued amount by request amount\n totalQueued -= request.amount;\n\n // Increment queue cursor if request was the next request to be processed\n if (requestId == withdrawalQueueCursor) withdrawalQueueCursor++;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[requestId];\n\n // If fund wallet's balance can cover request, rely on it only\n if (withdrawnAmount <= fundBalance) {\n underlying().safeTransferFrom(_msgSender(), request.account, withdrawnAmount);\n }\n // Else, cover request from both fund wallet and contract balances\n else {\n // Compute amount missing from fund wallet to cover request\n uint256 missingAmount = withdrawnAmount - fundBalance;\n\n // Decrease usable amount of underlying tokens accordingly\n usableUnderlyings -= missingAmount;\n\n // Transfer entire fund balance to request's emitter\n underlying().safeTransferFrom(_msgSender(), request.account, fundBalance);\n\n // Transfer missing amount from contract balance to request emitter\n underlying().safeTransfer(request.account, missingAmount);\n }\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Cancels a given withdrawal request. The request emitter receive back its\n * L-Tokens and no fees will be charged.\n * @param requestId The ID of the withdrawal request to cancel.\n */\n function cancelWithdrawalRequest(\n uint256 requestId\n ) public whenNotPaused notBlacklisted(_msgSender()) {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure request belongs to caller\n require(_msgSender() == request.account, \"L57\");\n\n // Decrease total amount queued accordingly\n totalQueued -= request.amount;\n\n // Delete the withdrawal request from queue\n delete withdrawalQueue[requestId];\n\n // Inform listeners of this cancelled withdrawal request activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Cancelled,\n NO_ID\n );\n\n // Mint back L-Tokens to account\n _mint(request.account, uint256(request.amount));\n }\n\n /**\n * @notice Used by the fund wallet to repatriate underlying tokens on the contract\n * whenever those are required to fulfill some withdrawal requests.\n * @dev The function will revert if repatriated amount makes the contract exceeding\n * the retention rate.\n * @param amount The amount of underlying tokens to repatriate.\n */\n function repatriate(uint256 amount) external onlyFund whenNotPaused {\n // Ensure the fund wallet has enough funds to repatriate\n require(amount <= underlying().balanceOf(fund), \"L58\");\n\n // Calculate new contract usable balance\n uint256 newBalance = usableUnderlyings + amount;\n\n // Ensure the new balance doesn't exceed the retention rate\n require(newBalance <= getExpectedRetained(), \"L59\");\n\n // Increase usable underlyings amount by repatriated amount\n usableUnderlyings += amount;\n\n // Transfer amount from fund wallet to contract\n underlying().safeTransferFrom(_msgSender(), address(this), amount);\n }\n\n /// @notice Used by owner to claim fees generated from successful withdrawals.\n function claimFees() external onlyOwner {\n // Ensure there are some fees to claim\n require(unclaimedFees > 0, \"L60\");\n\n // Ensure the contract holds enough underlying tokens to cover fees\n require(usableUnderlyings >= unclaimedFees, \"L61\");\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= unclaimedFees;\n\n // Store fees amount in memory and reset unclaimed fees amount\n uint256 fees = unclaimedFees;\n unclaimedFees = 0;\n\n // Transfer unclaimed fees to owner\n underlying().safeTransfer(owner(), fees);\n }\n}\n" + }, + "contracts/src/PreMining.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {LToken} from \"./LToken.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {Pausable} from \"@openzeppelin/contracts/security/Pausable.sol\";\n\n/**\n * @title PreMining\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n\n * @notice PreMining pool contract, allowing accounts to lock underlying tokens in a \n * pre-defined L-Token contract, over a given duration (in months), in exchange of \n * vested LDY rewards.\n * \n * @dev Intuition\n * \n * Lifecycle of a lockdrop pool is composed by 3 main phases:\n * 1) Deposit: During this phase, users can lock their underlying tokens.\n * 2) Claim: During this phase, users can claim their LDY rewards.\n * 3) Recovery: During this phase, owner can recover remaining ERC20 on the contract.\n * \n * Transitioning between two phases is manually triggered by contract's owner.\n * To ensure fair usage of this power and prevent potential misuse:\n * - the Recovery phase cannot start before 3 months after the end of rewards vesting,\n * - the Recovery phase cannot start before 3 months after the maximum lock end.\n * \n * Finally, note that this contract proxies main L-Token contract's functions:\n * - lock() --> deposit()\n * - instantUnlock() --> instantWithdrawal()\n * - requestUnlock() --> requestWithdrawal()\n * This design enables users to interact with the PreMining contract in a similar fashion\n * to the L-Token contract.\n * \n * @dev Definitions:\n * - Locker: An account that has locked underlying tokens in the pool.\n * \n * @custom:security-contact security@ledgity.com\n */\ncontract PreMining is Ownable2Step, Pausable {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Represents the lock information of an account.\n * @param amount Amount of underlying tokens locked.\n * @param duration Duration of the lock (in months).\n * @param hasUnlocked Whether the account has unlocked its locked tokens.\n * @param claimedRewards Amount of LDY rewards already claimed.\n * @param lockEndTimestamp Timestamp at which the account's lock ends.\n */\n struct AccountLock {\n uint240 amount;\n uint8 duration;\n bool hasUnlocked;\n uint216 claimedRewards;\n uint40 lockEndTimestamp;\n }\n\n /// @notice Holds the amount of LDY to be distributed to lockers.\n uint256 public immutable maxDistributedLDY;\n\n /// @notice Holds the maximum total amount of L-Tokens that can be locked.\n uint256 public immutable lockedHardCap;\n\n /// @notice Holds the minimum possible lock duration (in months).\n uint8 public immutable minLockDuration;\n\n /// @notice Holds the maximum possible lock duration (in months).\n uint8 public immutable maxLockDuration;\n\n /// @notice Holds the duration of LDY rewards vesting (in months).\n uint8 public immutable vestingDuration;\n\n /// @notice Holds a reference to the locked L-Token contract.\n LToken public immutable lToken;\n\n /// @notice Holds a reference to the L-Token underlying stablecoin.\n IERC20 public immutable underlyingToken;\n\n /// @notice Holds the max pool weight.\n uint256 public immutable maxWeight;\n\n /// @notice Holds a reference to the LDY token contract.\n IERC20 public ldyToken;\n\n /// @notice Holds lockers' participations informations.\n mapping(address => AccountLock) public accountsLocks;\n\n /// @notice Holds the total amount of locked underlying tokens.\n uint256 public totalLocked;\n\n /// @notice Holds whether the Deposit phase has ended.\n bool public hasDepositPhaseEnded;\n\n /// @notice Holds whether the Claim phase has started.\n bool public hasClaimPhaseStarted;\n\n /// @notice Holds whether the Recovery phase has started.\n bool public hasRecoveryPhaseStarted;\n\n /// @notice Holds the timestamp at which the Claim phase started.\n uint256 public claimPhaseStartTimestamp;\n\n /// @notice Holds an ordered queue of accounts that requested to unlock their tokens.\n address[] public unlockRequests;\n\n /// @notice Holds the index of the first request in the queue (a.k.a, next one to be processed).\n uint256 public unlockRequestsCursor;\n\n /// @notice Emitted to inform about a new lock/deposit.\n event Lock(address indexed account, uint256 amount, uint8 duration);\n\n /// @notice Top-level checks and code shared by both unlock functions.\n modifier safeUnlock() {\n // Ensure that the account's lock has ended\n require(accountsLocks[msg.sender].lockEndTimestamp <= block.timestamp, \"L68\");\n\n // Ensure the account hasn't already unlocked its tokens\n require(!accountsLocks[msg.sender].hasUnlocked, \"L69\");\n\n // Ensure the account has something to unlock\n require(accountsLocks[msg.sender].amount > 0, \"L70\");\n\n // Indicate that account has unlocked its tokens\n accountsLocks[msg.sender].hasUnlocked = true;\n _;\n }\n\n /**\n * @notice This constructor function etches the lockdrop terms in immutable states.\n * Ensuring that those terms cannot be modified after deployment.\n * @param lTokenAddress_ Address of the L-Token contract to use.\n * @param maxDistributedLDY_ Amount of LDY to be distributed to lockers.\n * @param lockedHardCap_ Maximum total amount of L-Tokens that can be locked.\n * @param minLockDuration_ Minimum possible lock duration (in months).\n * @param maxLockDuration_ Maximum possible lock duration (in months).\n * @param vestingDuration_ Duration of LDY rewards vesting (in months).\n */\n constructor(\n address lTokenAddress_,\n uint256 maxDistributedLDY_,\n uint256 lockedHardCap_,\n uint8 minLockDuration_,\n uint8 maxLockDuration_,\n uint8 vestingDuration_\n ) {\n // Ensure minLockDuration is at least 1 month\n require(minLockDuration_ >= 1, \"L72\");\n\n // Ensure minLockDuration is not greater than maxLockDuration\n require(minLockDuration_ <= maxLockDuration_, \"L73\");\n\n // Set immutable states\n lToken = LToken(lTokenAddress_);\n underlyingToken = IERC20(address(lToken.underlying()));\n lockedHardCap = lockedHardCap_;\n maxDistributedLDY = maxDistributedLDY_;\n minLockDuration = minLockDuration_;\n maxLockDuration = maxLockDuration_;\n vestingDuration = vestingDuration_;\n maxWeight = lockedHardCap * uint256(maxLockDuration);\n }\n\n /**\n * @notice Public implementation of Pausable's pausing and unpausing functions, but\n * restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Updates the LDY token contract address.\n * @dev As the first Ledgity Yield lockdrop campaigns will start before the LDY TGE,\n * this function allows the contract's owner to set the LDY token address once it\n * becomes available.\n * @param ldyTokenAddress Address of the LDY token contract.\n */\n function setLDYToken(address ldyTokenAddress) external onlyOwner {\n // Prevent owner from changing the LDY address after Claim phase has started\n require(!hasClaimPhaseStarted, \"L74\");\n\n // Set LDY token address\n ldyToken = IERC20(ldyTokenAddress);\n }\n\n /**\n * @notice Closes the Deposit phase. After calling this function, account won't be\n * able to lock additional underlying tokens anymore.\n */\n function endDepositPhase() external onlyOwner {\n hasDepositPhaseEnded = true;\n }\n\n /**\n * @notice Opens the Claim phase. After calling this function, lockers will be able\n * to start claiming their LDY rewards.\n */\n function startClaimPhase() external onlyOwner {\n // Ensure Claim phase has not already started\n require(!hasClaimPhaseStarted, \"L76\");\n\n // Ensure that LDY token address is available\n require(address(ldyToken) != address(0), \"L77\");\n\n // Set Claim phase as started and store the start timestamp\n hasClaimPhaseStarted = true;\n claimPhaseStartTimestamp = block.timestamp;\n }\n\n /**\n * @notice Opens the Recovery phase. After calling this function, the contract owner\n * will be able to recover remaining ERC20 tokens on the contract.\n * Note that this won't close the Claim phase and lockers will still be able to claim\n * their LDY rewards.\n */\n function startRecoveryPhase() external onlyOwner {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L79\");\n\n // Compute some durations in seconds\n uint256 threeMonthsInSecond = 3 * 30 days;\n uint256 vestingInSecond = uint256(vestingDuration) * 30 days;\n uint256 maxLockInSecond = uint256(maxLockDuration) * 30 days;\n\n // Compute timestamp of vesting end + 3 months\n uint256 afterVestingTimestamp = claimPhaseStartTimestamp +\n vestingInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the end of reward vesting\n // This prevents owner from recovering LDY before lockers can claim their rewards\n require(block.timestamp >= afterVestingTimestamp, \"L80\");\n\n // Compute end of maximum lock + 3 months\n // Note that claimPhaseStartTimestamp is used for simplicity even if it can exist a time\n // span between Deposit and Claim phases.\n uint256 afterMaxLockTimestamp = claimPhaseStartTimestamp +\n maxLockInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the maximum lock end\n // This prevents owner from recovering underlying tokens before lockers can unlock those\n require(block.timestamp >= afterMaxLockTimestamp, \"L81\");\n\n // Set recovery phase as started\n hasRecoveryPhaseStarted = true;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address. Will revert if\n * recovery phase has not started yet or if the contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) external onlyOwner {\n // Ensure recovery phase has started\n require(hasRecoveryPhaseStarted, \"L82\");\n\n // Create a reference to token's contract\n IERC20 tokenContract = IERC20(tokenAddress);\n\n // Ensure there is enough tokens to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L83\");\n\n // Transfer the recovered token amount to the sender (owner)\n tokenContract.safeTransfer(msg.sender, amount);\n }\n\n /**\n * @notice Compute the total amount of LDY rewards that a given account is eligible to.\n * @dev Note: This function neither considers vesting nor already claimed rewards.\n * @param account The account to compute the eligible rewards of.\n * @return The total amount of LDY rewards that the account is eligible to.\n */\n function eligibleRewardsOf(address account) public view returns (uint256) {\n // Compute account's lock weight\n uint256 lockerWeight = accountsLocks[account].amount * accountsLocks[account].duration;\n\n // Compute amount of LDY that this locker is eligible to\n if (maxWeight == 0) return 0;\n else return (maxDistributedLDY * lockerWeight) / maxWeight;\n }\n\n /**\n * @notice Allows locking a specified amount of underlying tokens for a given duration.\n * By locking, an account became eligible to a portion of the distributed LDY rewards.\n * @dev This function proxies LToken.deposit()\n * @dev Lockers can extend their lock duration by calling this function again with a\n * greater duration and 0 as amount.\n * @param amount Amount of underlying tokens to lock.\n * @param duration Duration of the lock (in months).\n */\n function lock(uint256 amount, uint8 duration) external whenNotPaused {\n // Ensure Deposit phase has not ended yet\n require(!hasDepositPhaseEnded, \"L84\");\n\n // Ensure account hasn't already unlocked a past lock\n require(!accountsLocks[msg.sender].hasUnlocked, \"L71\");\n\n // Ensure lock duration is in valid range\n require(duration >= minLockDuration && duration <= maxLockDuration, \"L85\");\n\n // Ensure it won't exceed the hardcap\n require(totalLocked + amount <= uint256(lockedHardCap), \"L86\");\n\n // Increase account's locked amount\n accountsLocks[msg.sender].amount += uint240(amount);\n\n // Increase total locked amount accordingly\n totalLocked += amount;\n\n // Use existing lock duration if greater than the new one\n uint8 existingDuration = accountsLocks[msg.sender].duration;\n uint8 appliedDuration = existingDuration > duration ? existingDuration : duration;\n\n // Update account's lock duration\n accountsLocks[msg.sender].duration = appliedDuration;\n\n // Update account's lock end timestamp\n accountsLocks[msg.sender].lockEndTimestamp = uint40(\n block.timestamp + uint40(appliedDuration) * 30 days\n );\n\n // Emit a Lock event\n emit Lock(msg.sender, amount, appliedDuration);\n\n // If amount is 0, skip deposit\n if (amount == 0) return;\n\n // Transfer underlyingToken from account to contract\n underlyingToken.safeTransferFrom(msg.sender, address(this), amount);\n\n // Deposit USDC in the L-Token contract\n underlyingToken.safeApprove(address(lToken), amount);\n lToken.deposit(amount);\n }\n\n /**\n * @notice Allows the caller to instaneously unlock its locked amount of underlying\n * tokens.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestUnlock() function otherwise.\n */\n function instantUnlock() external whenNotPaused safeUnlock {\n // Retrieve underlying tokens from the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.instantWithdrawal(unlockedAmount);\n\n // Transfer underlying tokens back to caller\n underlyingToken.safeTransfer(msg.sender, unlockedAmount);\n }\n\n /**\n * @notice Allows the call to request for the unlocking of its locked amount of\n * underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n */\n function requestUnlock() external payable whenNotPaused safeUnlock {\n // Put account in the unlock requests queue\n unlockRequests.push(msg.sender);\n\n // Request underlying tokens to the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.requestWithdrawal{value: msg.value}(unlockedAmount);\n }\n\n /**\n * @notice Processes queued unlock requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n */\n function processUnlockRequests() external onlyOwner {\n // Store the current request ID to process\n uint256 processedId = unlockRequestsCursor;\n\n // Loop over remaining requests\n while (processedId < unlockRequests.length) {\n // Prevent OOG by stopping request processing if there is not enough gas left\n // to continue the loop and properly end the function call.\n if (gasleft() < 45000) break;\n\n // Retrieve the request account\n address unlockAccount = unlockRequests[processedId];\n\n // Retrieve the unlocked amount\n uint256 unlockAmount = accountsLocks[unlockAccount].amount;\n\n // If the request has already been processed, skip it\n if (unlockAccount != address(0)) {\n // If the contract doesn't hold enough underlying tokens to process the request, stop here\n if (underlyingToken.balanceOf(address(this)) < unlockAmount) break;\n\n // Delete the request\n delete unlockRequests[processedId];\n\n // Transfer underlying back to account\n underlyingToken.safeTransfer(unlockAccount, unlockAmount);\n }\n\n // Increment processed request ID\n processedId++;\n }\n\n // Write back the cursor in storage\n unlockRequestsCursor = processedId;\n }\n\n /**\n * @notice Computes the amount of LDY rewards available to claim for a given account.\n * @dev This function considers vesting and already claimed rewards.\n * @param account The account to compute the available rewards of.\n * @return The amount of LDY rewards available to claim.\n */\n function availableToClaim(address account) public view returns (uint256) {\n // Compute total amount of rewards allocated to this locker\n uint256 totalEligibleRewards = eligibleRewardsOf(account);\n\n // Compute vesting duration in seconds\n uint256 vestingInSeconds = uint256(vestingDuration) * 30 days;\n\n // Compute elapsed months since claim phase started, and cap it to vesting duration\n uint256 elapsedTime = block.timestamp - claimPhaseStartTimestamp;\n if (elapsedTime > vestingInSeconds) elapsedTime = vestingInSeconds;\n\n // Compute total available to claim (proportionally to elapsed time)\n uint256 totalAvailableToClaim = (totalEligibleRewards * elapsedTime) / vestingInSeconds;\n\n // Else return net claimable (available minus already claimed)\n return totalAvailableToClaim - accountsLocks[account].claimedRewards;\n }\n\n /// @notice Allows the caller to claim its available LDY rewards.\n function claimRewards() external whenNotPaused {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L87\");\n\n // Compute claimable LDY rewards\n uint256 claimableLDY = availableToClaim(msg.sender);\n\n // Increase account claimed amount accordingly\n accountsLocks[msg.sender].claimedRewards += uint216(claimableLDY);\n\n // Transfer rewards to account\n ldyToken.safeTransfer(msg.sender, claimableLDY);\n }\n}\n" + } + }, + "settings": { + "evmVersion": "london", + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/contracts/hardhat/deployments/arbitrum/solcInputs/d4bb825b27822879e0607341255f6d62.json b/contracts/hardhat/deployments/arbitrum/solcInputs/d4bb825b27822879e0607341255f6d62.json new file mode 100644 index 00000000..c7b17cdf --- /dev/null +++ b/contracts/hardhat/deployments/arbitrum/solcInputs/d4bb825b27822879e0607341255f6d62.json @@ -0,0 +1,165 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeTo(address newImplementation) public virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../../../security/PausableUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract unpausable.\n */\nabstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {\n function __ERC20Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __ERC20Pausable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Wrapper.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../utils/SafeERC20Upgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of the ERC20 token contract to support token wrapping.\n *\n * Users can deposit and withdraw \"underlying tokens\" and receive a matching number of \"wrapped tokens\". This is useful\n * in conjunction with other modules. For example, combining this wrapping mechanism with {ERC20Votes} will allow the\n * wrapping of an existing \"basic\" ERC20 into a governance token.\n *\n * _Available since v4.2._\n *\n * @custom:storage-size 51\n */\nabstract contract ERC20WrapperUpgradeable is Initializable, ERC20Upgradeable {\n IERC20Upgradeable private _underlying;\n\n function __ERC20Wrapper_init(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n __ERC20Wrapper_init_unchained(underlyingToken);\n }\n\n function __ERC20Wrapper_init_unchained(IERC20Upgradeable underlyingToken) internal onlyInitializing {\n require(underlyingToken != this, \"ERC20Wrapper: cannot self wrap\");\n _underlying = underlyingToken;\n }\n\n /**\n * @dev See {ERC20-decimals}.\n */\n function decimals() public view virtual override returns (uint8) {\n try IERC20MetadataUpgradeable(address(_underlying)).decimals() returns (uint8 value) {\n return value;\n } catch {\n return super.decimals();\n }\n }\n\n /**\n * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\n */\n function underlying() public view returns (IERC20Upgradeable) {\n return _underlying;\n }\n\n /**\n * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\n */\n function depositFor(address account, uint256 amount) public virtual returns (bool) {\n address sender = _msgSender();\n require(sender != address(this), \"ERC20Wrapper: wrapper can't deposit\");\n SafeERC20Upgradeable.safeTransferFrom(_underlying, sender, address(this), amount);\n _mint(account, amount);\n return true;\n }\n\n /**\n * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\n */\n function withdrawTo(address account, uint256 amount) public virtual returns (bool) {\n _burn(_msgSender(), amount);\n SafeERC20Upgradeable.safeTransfer(_underlying, account, amount);\n return true;\n }\n\n /**\n * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal\n * function that can be exposed with access control if desired.\n */\n function _recover(address account) internal virtual returns (uint256) {\n uint256 value = _underlying.balanceOf(address(this)) - totalSupply();\n _mint(account, value);\n return value;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable2Step.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "contracts/src/abstracts/base/BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"../GlobalOwnableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"../GlobalRestrictableUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../RecoverableUpgradeable.sol\";\n\n/**\n * @title BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract acts as a base for numerous contracts in this codebase,\n * minimizing code repetition and enhancing readability and maintainability.\n *\n * @dev For further details, see \"Base\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract BaseUpgradeable is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n GlobalPausableUpgradeable,\n GlobalRestrictableUpgradeable,\n RecoverableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_\n ) internal onlyInitializing {\n __UUPSUpgradeable_init();\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n __Recoverable_init_unchained();\n }\n\n function __Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/base/ERC20BaseUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {ERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {ERC20PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"./BaseUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"../GlobalPausableUpgradeable.sol\";\n\n/**\n * @title ERC20BaseUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This abstract contract is an extension of BaseUpgradeable intended to be used\n * as a base for ERC20 tokens contracts.\n *\n * @dev For further details, see \"ERC20BaseUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract ERC20BaseUpgradeable is\n ERC20Upgradeable,\n BaseUpgradeable,\n ERC20PausableUpgradeable\n{\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param name_ The display name of the token.\n * @param symbol_ The symbol of the token.\n */\n function __ERC20Base_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n string memory name_,\n string memory symbol_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __ERC20_init(name_, symbol_);\n __ERC20Pausable_init_unchained();\n }\n\n function __ERC20Base_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and PausableUpgradeable parent contracts.\n * The GlobalPausableUpgradeable version is preferred because it checks the pause\n * state from the GlobalPause contract.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, PausableUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @dev Required override of _beforeTokenTransfer() which is implemented by both\n * ERC20PausableUpgradeable and ERC20Upgradeable parent contracts.\n * The ERC20PausableUpgradeable version is preferred because it also checks that\n * the contract is not paused before allowing the transfer.\n * @inheritdoc ERC20PausableUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n )\n internal\n virtual\n override(ERC20PausableUpgradeable, ERC20Upgradeable)\n whenNotPaused\n notBlacklisted(from)\n notBlacklisted(to)\n {\n ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalOwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {GlobalOwner} from \"../GlobalOwner.sol\";\n\n/**\n * @title GlobalOwnableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit ownership from the specified GlobalOwner\n * contract (see GlobalOwner.sol). This design facilitates centralized management\n * of ownership for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalOwner state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalOwnableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalOwnableUpgradeable is Initializable, OwnableUpgradeable {\n /**\n * @notice The GlobalOwner contract the ownership will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalOwner private _globalOwner;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __GlobalOwnable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init_unchained(globalOwner_);\n // Note: __Ownable_init() doesn't have to be called as the overriden owner()\n // function no longer rely on the _owner state. Since __Ownable_init() only sets\n // the initial _owner value, calling it would have no effect.\n }\n\n function __GlobalOwnable_init_unchained(address globalOwner_) internal onlyInitializing {\n _globalOwner = GlobalOwner(globalOwner_);\n }\n\n /**\n * @notice Retrieves the address of GlobalOwner contract.\n * @return The address of the GlobalOwner contract.\n */\n function globalOwner() public view returns (address) {\n return address(_globalOwner);\n }\n\n /**\n * @notice Override of OwnableUpgradeable.owner() that retrieves the owner's address\n * from the GlobalOwner contract instead.\n * @return The address of the owner\n */\n function owner() public view override returns (address) {\n return _globalOwner.owner();\n }\n\n /**\n * @notice Override of OwnableUpgradeable.transferOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function transferOwnership(address newOwner) public view override onlyOwner {\n newOwner; // Silence unused variable compiler warning\n revert(\"L8\");\n }\n\n /**\n * @notice Override of OwnableUpgradeable.renounceOwnership() that always reverts.\n * Ownership is managed by the GlobalOwner contract and must be modified there.\n */\n function renounceOwnership() public view override onlyOwner {\n revert(\"L65\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalPausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalPause} from \"../GlobalPause.sol\";\n\n/**\n * @title GlobalPausableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a pause state from the specified GlobalPause\n * contract (see GlobalPause.sol). This design facilitates centralized management of\n * pause state for all the Ledgity Yield contracts.\n *\n * @dev Security measure\n * The _globalPause state must be set at initialization time and, for evident security\n * reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalPausableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalPausableUpgradeable is Initializable, PausableUpgradeable {\n /**\n * @notice The GlobalPause contract the pause state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalPause private _globalPause;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalPause_ The address of the GlobalPause contract.\n */\n function __GlobalPausable_init(address globalPause_) internal onlyInitializing {\n __Pausable_init();\n __GlobalPausable_init_unchained(globalPause_);\n }\n\n function __GlobalPausable_init_unchained(address globalPause_) internal onlyInitializing {\n _globalPause = GlobalPause(globalPause_);\n }\n\n /**\n * @notice Retrieves the address of GlobalPause contract.\n * @return The address of the GlobalPause contract.\n */\n function globalPause() public view returns (address) {\n return address(_globalPause);\n }\n\n /**\n * @notice Override of PausableUpgradeable.pause() that retrieves the pause state\n * from the GlobalPause contract instead.\n * @return Whether the contract is paused or not.\n */\n function paused() public view virtual override returns (bool) {\n return _globalPause.paused();\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/GlobalRestrictableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalBlacklist} from \"../GlobalBlacklist.sol\";\n\n/**\n * @title GlobalRestrictableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts will inherit a blacklist state from the specified\n * GlobalBlacklist contract (see GlobalBlacklist.sol). This design facilitates\n * centralized management of a blacklist for all the Ledgity Yield contracts.\n *\n * @dev Security measure:\n * The _globalBlacklist state must be set at initialization time and, for evident\n * security reasons, cannot be changed afterward.\n *\n * @dev For further details, see \"GlobalRestrictableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract GlobalRestrictableUpgradeable is Initializable {\n /**\n * @notice The GlobalBlacklist contract the blacklist state will be inherited from.\n * @dev This state is private so derived contracts cannot change its value.\n */\n GlobalBlacklist private _globalBlacklist;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n */\n function __GlobalRestrictable_init(address globalBlacklist_) internal onlyInitializing {\n __GlobalRestrictable_init_unchained(globalBlacklist_);\n }\n\n function __GlobalRestrictable_init_unchained(\n address globalBlacklist_\n ) internal onlyInitializing {\n _globalBlacklist = GlobalBlacklist(globalBlacklist_);\n }\n\n /**\n * @notice Retrieves the address of GlobalBlacklist contract.\n * @return The address of the GlobalBlacklist contract.\n */\n function globalBlacklist() public view returns (address) {\n return address(_globalBlacklist);\n }\n\n /**\n * @notice Reverts if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n */\n modifier notBlacklisted(address account) {\n require(isBlacklisted(account) == false, \"L9\");\n _;\n }\n\n /**\n * @notice Checks if the given account is blacklisted by the GlobalBlacklist contract.\n * @param account Address to verify.\n * @return Whether the account is blacklisted.\n */\n function isBlacklisted(address account) internal view returns (bool) {\n return _globalBlacklist.isBlacklisted(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/InvestUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\nimport {GlobalPausableUpgradeable} from \"./GlobalPausableUpgradeable.sol\";\nimport {GlobalRestrictableUpgradeable} from \"./GlobalRestrictableUpgradeable.sol\";\nimport \"./base/BaseUpgradeable.sol\";\nimport {RecoverableUpgradeable} from \"../abstracts/RecoverableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {APRHistory as APRH} from \"../libs/APRHistory.sol\";\nimport {SUD} from \"../libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title InvestUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with utilities to manage an invested token,\n * users' investment periods, rewards calculations, virtual balances, and auto-compounding.\n *\n * @dev Intuition:\n * This contract primarily exists for code splitting and reusability. It unburdens the\n * LToken contract code, making it easier to understand and maintain.\n *\n * This contract is generic because it may be used in the LDYStaking contract in the future.\n *\n * @dev Definitions:\n * - Investment: The act of depositing or investing tokens into the contract.\n * - Investment period: Time between the last invested amount change and the present.\n * - Virtual balance: Temporary storage for account rewards, used when those can't be\n * distributed between investment periods.\n * - Rewards redirection: Mechanism allowing an account to redirect its rewards to another.\n *\n * @dev Derived contract must:\n * - Set invested token during initialization\n * - Implement _investmentOf() function\n * - (optionally) Implement _distributeRewards() function\n *\n * @dev For further details, see \"InvestmentUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract InvestUpgradeable is BaseUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using APRH for APRH.Pack[];\n\n /**\n * @notice Represents an account's investment period.\n * @param timestamp The timestamp of the most recent rewards distribution.\n * @param ref The reference of the last APR checkpoint at that timestamp.\n */\n struct InvestmentPeriod {\n uint40 timestamp; // Supports dates up to 20/02/36812\n APRH.Reference ref;\n }\n\n /**\n * @notice Represents the investment details of an account.\n * @param period The current investment period of the account.\n * @param virtualBalance May hold a part of account rewards until they are claimed.\n */\n struct AccountDetails {\n InvestmentPeriod period;\n uint256 virtualBalance;\n }\n\n /// @notice Holds a reference to the invested token's contract.\n IERC20Upgradeable private _invested;\n\n /// @notice Holds investment details of each account.\n mapping(address => AccountDetails) internal accountsDetails;\n\n /// @notice Holds an history of the APR value over time (see APRHistory.sol).\n APRH.Pack[] private _aprHistory;\n\n /// @notice Holds active rewards redirections in both from->to and to->from[] ways.\n mapping(address => address) public rewardsRedirectsFromTo;\n mapping(address => address[]) public rewardsRedirectsToFrom;\n\n /// @notice Is used to prevent infinite loop in _beforeInvestmentChange().\n bool private _isClaiming;\n\n /**\n * @notice Emitted to inform listeners about a change in the APR's value.\n * @param newAPRUD7x3 The new APR in UD7x3 format.\n */\n event APRChangeEvent(uint16 newAPRUD7x3);\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param invested_ The address of the invested token contract.\n */\n function __Invest_init(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address invested_\n ) internal onlyInitializing {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n __Invest_init_unchained(invested_);\n }\n\n function __Invest_init_unchained(address invested_) internal onlyInitializing {\n // Set invested token\n _invested = IERC20Upgradeable(invested_);\n\n // Define initial APR to 0%. This would prevent getAPR() from reverting because\n // of an empty APR history\n _aprHistory.setAPR(0);\n }\n\n /**\n * @notice Retrieves the reference to the invested token contract.\n * @return The reference to the invested token contract.\n */\n function invested() public view returns (IERC20Upgradeable) {\n return _invested;\n }\n\n /**\n * @notice Updates the investment APR. Restricted to owner.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(uint16 aprUD7x3) public onlyOwner {\n _aprHistory.setAPR(aprUD7x3);\n emit APRChangeEvent(aprUD7x3);\n }\n\n /**\n * @notice Retrieves the most recently set APR.\n * @return The current APR in UD7x3 format.\n */\n function getAPR() public view returns (uint16) {\n return _aprHistory.getAPR();\n }\n\n /**\n * @notice Enables redirection of rewards from one account to another.\n * @param from The address of the account to redirect rewards from.\n * @param to The address of the account to redirect rewards to.\n */\n function startRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure the address is not already redirecting rewards\n require(rewardsRedirectsFromTo[from] == address(0), \"L62\");\n\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L12\");\n require(to != address(0), \"L13\");\n\n // Ensure 'from' and 'to' addresses are distinct\n require(from != to, \"L14\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L15\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Activate rewards redirection\n rewardsRedirectsFromTo[from] = to;\n rewardsRedirectsToFrom[to].push(from);\n }\n\n /**\n * @notice Disable an active rewards redirection.\n * @param from The address of the account to stop redirecting rewards from.\n * @param to The address of the account to stop redirecting rewards to.\n */\n function stopRewardsRedirection(\n address from,\n address to\n ) public whenNotPaused notBlacklisted(from) notBlacklisted(to) {\n // Ensure neither 'from' nor 'to' are the zero address\n require(from != address(0), \"L16\");\n require(to != address(0), \"L17\");\n\n // Ensure function caller is either the owner or the 'from' address\n require(_msgSender() == owner() || _msgSender() == from, \"L18\");\n\n // Ensure a rewards redirection was active\n require(rewardsRedirectsFromTo[from] == to, \"L19\");\n\n // Distribute current rewards and reset investment periods of both accounts\n _beforeInvestmentChange(from, true);\n _beforeInvestmentChange(to, true);\n\n // Retrieve 'from' index in the redirection array of 'to'\n int256 fromIndex = -1;\n for (uint256 i = 0; i < rewardsRedirectsToFrom[to].length; i++) {\n if (rewardsRedirectsToFrom[to][i] == from) {\n fromIndex = int256(i);\n break;\n }\n }\n\n // fromIndex should never be -1 at this point\n assert(fromIndex >= 0);\n\n // Deactivate rewards redirection\n rewardsRedirectsFromTo[from] = address(0);\n rewardsRedirectsToFrom[to][uint256(fromIndex)] = rewardsRedirectsToFrom[to][\n rewardsRedirectsToFrom[to].length - 1\n ];\n rewardsRedirectsToFrom[to].pop();\n }\n\n /**\n * @notice Retrieves the total amount of tokens invested by the given account.\n * @dev Derived contracts must implement this function.\n * @param account The account to get the investment of.\n * @return The total amount of tokens invested by the given account.\n */\n function _investmentOf(address account) internal view virtual returns (uint256);\n\n /**\n * @notice Distributes a specified amount of rewards to a given account.\n * @dev Derived contracts may optionally implement this function.\n * @dev Implementations must return true to indicate a successful distribution, and\n * false otherwise. If it returns false, the rewards will be added to the account's\n * virtual balance, in order to be claimed later.\n * @param account The account to claim the rewards of.\n * @param amount The amount of rewards to claim.\n * @return Whether the rewards distribution was successfull.\n */\n function _distributeRewards(address account, uint256 amount) internal virtual returns (bool) {\n account; // Silence unused variables warning\n amount;\n return false;\n }\n\n /**\n * @notice Computes the rewards accrued over a specified period of time, based on a\n * given APR and amount of invested tokens.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param beginTimestamp The moment the period commenced.\n * @param endTimestamp The moment the period concluded.\n * @param aprUD7x3 The APR during this period, in UD7x3 format.\n * @param investedAmount The amount of tokens deposited/invested during the period.\n * @return The amount of rewards generated during the period.\n */\n function _calculatePeriodRewards(\n uint40 beginTimestamp,\n uint40 endTimestamp,\n uint16 aprUD7x3,\n uint256 investedAmount\n ) internal view returns (uint256) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Compute the number of elapsed years\n uint256 elapsedTimeSUD = SUD.fromInt(endTimestamp - beginTimestamp, d);\n uint256 elapsedYearsSUD = (elapsedTimeSUD * SUD.fromInt(1, d)) / SUD.fromInt(365 days, d);\n\n // Compute the growth in invested amount (thanks to rewards)\n uint256 aprSUD = SUD.fromRate(aprUD7x3, d);\n uint256 growthSUD = (elapsedYearsSUD * aprSUD) / SUD.fromInt(1, d);\n\n // Compute and return the rewards\n uint256 investedAmountSUD = SUD.fromAmount(investedAmount, d);\n uint256 rewardsSUD = (investedAmountSUD * growthSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(rewardsSUD, d);\n }\n\n /**\n * @notice Computes the sum of given account's invested amount, plus invested amount\n * of all accounts that recursively redirect rewards to this account.\n * @param account The account to calculate the deep investment of.\n * @return deepInvestedAmount The deep invested amount.\n */\n function _deepInvestmentOf(address account) internal view returns (uint256 deepInvestedAmount) {\n // Consider account's direct investment\n deepInvestedAmount += _investmentOf(account);\n\n // But also the deep investments of all accounts redirecting rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n deepInvestedAmount += _deepInvestmentOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Computes the amount of unclaimed/undistributed rewards of a given account.\n * @dev For further details, see \"InvestUpgradeable > Rewards calculation\" section of\n * the whitepaper.\n * @param account The account to calculate the unclaimed rewards of.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n * @return rewards The amount of unclaimed/undistributed rewards of the given account.\n */\n function _rewardsOf(\n address account,\n bool autocompound\n ) internal view returns (uint256 rewards) {\n // Retrieve account's investment details\n AccountDetails memory details = accountsDetails[account];\n\n // Retrieve account's deep invested amount\n uint256 investedAmount = _deepInvestmentOf(account);\n\n // Return 0 if the account has never invested or has no invested amount\n if (details.period.timestamp == 0 || investedAmount == 0) return 0;\n\n // Retrieve reference and data of APR checkpoint at which started investment period\n APRH.Reference memory currRef = details.period.ref;\n APRH.CheckpointData memory currCheckpoint = _aprHistory.getDataFromReference(currRef);\n\n // Retrieve reference of latest APR checkpoint\n APRH.Reference memory latestRef = _aprHistory.getLatestReference();\n\n // 1) Fill rewards with virtual balance (rewards not claimed/distributed yet)\n // See \"InvestUpgradeable > Yield calculation > 1)\" section of the whitepaper\n rewards = details.virtualBalance;\n\n // If start checkpoint is not the latest one\n if (!APRH.eq(currRef, latestRef)) {\n // Retrieve reference and data of APR checkpoint that comes after start checkpoint\n APRH.Reference memory nextRef = APRH.incrementReference(currRef);\n APRH.CheckpointData memory nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // 2) Calculate rewards from investment period start to next checkpoint\n // See \"InvestUpgradeable > Yield calculation > 2)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n\n // 3) Calculate rewards for each crossed pair of checkpoints\n // See \"InvestUpgradeable > Yield calculation > 3)\" section of the whitepaper\n while (true) {\n // Set next checkpoint as the current one\n currRef = nextRef;\n currCheckpoint = nextCheckpoint;\n\n // Break if current checkpoint is the latest one\n if (APRH.eq(currRef, latestRef)) break;\n\n // Else, retrieve the new next checkpoint\n nextRef = APRH.incrementReference(currRef);\n nextCheckpoint = _aprHistory.getDataFromReference(nextRef);\n\n // Calculate rewards between the current pair of checkpoints\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n nextCheckpoint.timestamp,\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n\n // 4) Calculate rewards from the latest checkpoint to now\n // See \"InvestUpgradeable > Yield calculation > 4)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n currCheckpoint.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n } else {\n // 2.bis) Calculate rewards from investment period start to now\n // See \"InvestUpgradeable > Yield calculation > 2.bis)\" section of the whitepaper\n rewards += _calculatePeriodRewards(\n details.period.timestamp,\n uint40(block.timestamp),\n currCheckpoint.aprUD7x3,\n investedAmount + (autocompound ? rewards : 0)\n );\n }\n }\n\n /**\n * @notice Recursively resets the investment period of the specified account and of\n * all accounts that directly or indirectly redirect rewards to this account.\n * @param account The account to deeply reset the investment period of.\n */\n function _deepResetInvestmentPeriodOf(address account) internal {\n // Reset account investment period timestamp and APR checkpoint to latest ones\n accountsDetails[account].period.timestamp = uint40(block.timestamp);\n accountsDetails[account].period.ref = _aprHistory.getLatestReference();\n\n // Also reset the ones of all accounts that recursively redirect rewards to this account\n for (uint256 i = 0; i < rewardsRedirectsToFrom[account].length; i++) {\n _deepResetInvestmentPeriodOf(rewardsRedirectsToFrom[account][i]);\n }\n }\n\n /**\n * @notice Hook to be invoked before the invested amount of an account changes. It\n * ensures that rewards are distributed and that account's investment period is reset.\n * @param account The account whose invested amount is going to change.\n * @param autocompound Whether to autocompound the rewards between APR checkpoints.\n */\n function _beforeInvestmentChange(address account, bool autocompound) internal {\n // This hook is called inside LToken._beforeTokenTransfer() and as new tokens are\n // minted in LToken._distributeRewards(), this guards against infinite loop.\n if (_isClaiming) return;\n\n // LToken._beforeTokenTransfer() calls this hook for both involved addresses.\n // As first call will treat both addresses, the second call would be redundant.\n // Therefore, we skip accounts already processed in this block to save up some gas.\n if (accountsDetails[account].period.timestamp == uint40(block.timestamp)) return;\n\n // If account redirects its rewards\n address redirectRewardsTo = rewardsRedirectsFromTo[account];\n if (redirectRewardsTo != address(0)) {\n // Call hook on redirection target (this will indirectly reset the investment\n // of this source account) and return\n _beforeInvestmentChange(redirectRewardsTo, autocompound);\n return;\n }\n\n // Else, compute account's undistributed/unclaimed rewards\n uint256 rewards = _rewardsOf(account, autocompound);\n\n // If there are some rewards\n if (rewards > 0) {\n // Try to distribute rewards to account\n _isClaiming = true;\n bool distributed = _distributeRewards(account, rewards);\n _isClaiming = false;\n\n // If rewards have not been distributed, accumulate them in account's virtual balance\n if (!distributed) accountsDetails[account].virtualBalance = rewards;\n }\n\n // Finally, deeply reset investment period of the account\n _deepResetInvestmentPeriodOf(account);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/abstracts/RecoverableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Conracts\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./GlobalOwnableUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title RecoverableUpgradeable\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Derived contracts are provided with helper functions allowing the recovery of\n * assets accidentally sent to them.\n *\n * @dev Where are utilities Ether, ERC721, etc.?\n * This abstract contract currently supports only ERC20 tokens. Derived contracts\n * in this codebase currently do not implement the necessary functions to receive Ether\n * or ERC721/ERC1155 tokens, so no recovery functions are provided for these assets.\n *\n * @dev For further details, see \"RecoverableUpgradeable\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nabstract contract RecoverableUpgradeable is Initializable, GlobalOwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Initializer functions of the contract. They replace the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function __Recoverable_init(address globalOwner_) internal onlyInitializing {\n __GlobalOwnable_init(globalOwner_);\n __Recoverable_init_unchained();\n }\n\n function __Recoverable_init_unchained() internal onlyInitializing {}\n\n /**\n * @notice Recovers a specified amount of a given token address. Will fail if the\n * contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) public virtual onlyOwner {\n // Ensure the specified amount is not zero\n require(amount > 0, \"L10\");\n\n // Create a reference to token's contract\n IERC20Upgradeable tokenContract = IERC20Upgradeable(tokenAddress);\n\n // Ensure there is enough token to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L11\");\n\n // Transfer the recovered token amount to the sender\n tokenContract.safeTransfer(_msgSender(), amount);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add\n * new variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/src/GlobalBlacklist.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalBlacklist\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global mapping of blacklisted accounts shared by all contracts of the\n * Ledgity Yield codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalRestrictableUpgradeable abstract contract. This provides them with modifiers\n * and getter functions to easily check against this global blacklist.\n *\n * @dev For further details, see \"GlobalBlacklist\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalBlacklist is Initializable, UUPSUpgradeable, GlobalOwnableUpgradeable {\n /**\n * @notice Mapping of accounts to their blacklist status.\n * @dev This mapping is made private and isBlacklisted() should be used instead.This\n * helps saving gas in some scenario. See isBlacklisted() documentation for more details.\n */\n mapping(address => bool) private _list;\n\n /// @dev Emitted when `account` is blacklisted.\n event Blacklisted(address account);\n\n /// @dev Emitted when `account` is unblacklisted.\n event Unblacklisted(address account);\n\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @notice Adds a given account to the blacklist.\n * @param account The account's address to be blacklisted.\n */\n function blacklist(address account) external onlyOwner {\n require(account != address(0), \"L20\");\n _list[account] = true;\n emit Blacklisted(account);\n }\n\n /**\n * @notice Removes a given account from the blacklist.\n * @param account The account's address to be un-blacklisted.\n */\n function unBlacklist(address account) external onlyOwner {\n _list[account] = false;\n emit Unblacklisted(account);\n }\n\n /**\n * @notice Checks whether a given account is blacklisted.\n * @param account Address of the account to check.\n * @return 'true' if the account is blacklisted, 'false' otherwise\n */\n function isBlacklisted(address account) external view returns (bool) {\n // Gas optimization: Avoid accessing storage if account is the zero address\n // (e.g, during a mint or a burn of tokens)\n if (account == address(0)) return false;\n\n // Else, return current account's blacklist status\n return _list[account];\n }\n}\n" + }, + "contracts/src/GlobalOwner.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {Ownable2StepUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\n/**\n * @title GlobalOwner\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds the address of a global owner account shared by all contracts of the\n * Ledgity Yield's codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalOwnableUpgradeable abstract contract. This provides them with an overriden\n * owner() function that retrieves the owner's address from this contract instead.\n *\n * @dev For further details, see \"GlobalOwner\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalOwner is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable {\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n */\n function initialize() public initializer {\n __Ownable2Step_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n}\n" + }, + "contracts/src/GlobalPause.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {GlobalOwnableUpgradeable} from \"./abstracts/GlobalOwnableUpgradeable.sol\";\n\n/**\n * @title GlobalPause\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Holds a global pause state shared by all contracts of the Ledgity Yield\n * codebase.\n *\n * @dev Specifically, some contracts within the codebase inherit from the\n * GlobalPausableUpgradeable abstract contract. This provides them with an overriden\n * paused() function that retrieves the pause state from this contract instead.\n *\n * @dev For further details, see \"GlobalPause\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\ncontract GlobalPause is\n Initializable,\n UUPSUpgradeable,\n GlobalOwnableUpgradeable,\n PausableUpgradeable\n{\n /**\n * @notice Prevents implementation contract from being initialized as recommended by\n * OpenZeppelin.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n */\n function initialize(address globalOwner_) public initializer {\n __GlobalOwnable_init(globalOwner_);\n __Pausable_init();\n __UUPSUpgradeable_init();\n }\n\n /**\n * @notice Override of UUPSUpgradeable._authorizeUpgrade() function restricted to\n * global owner. It is called by the proxy contract during an upgrade.\n * @param newImplementation The address of the new implementation contract.\n */\n function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}\n\n /**\n * @dev Public implementation of PausableUpgradeable's pausing and unpausing functions\n * but restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n}\n" + }, + "contracts/src/interfaces/ITransfersListener.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\ninterface ITransfersListener {\n function onLTokenTransfer(address from, address to, uint256 amount) external;\n}\n" + }, + "contracts/src/LDYStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {BaseUpgradeable} from \"./abstracts/base/BaseUpgradeable.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @title LDYStaking\n * @custom:security-contact security@ledgity.com\n *\n * @dev This contract implements tierOf() function from LDYStaking as it's the only\n * one the LToken contract relies on.\n *\n * @custom:security-contact security@ledgity.com\n */\ncontract LDYStaking is BaseUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Represents a user staking info in array.\n * @param stakedAmount Amount of the stake.\n * @param unStakeAt Unstake at.\n * @param duration Staking period in seconds.\n * @param rewardPerTokenPaid Reward per token paid.\n * @param rewards Rewards to be claimed.\n */\n struct StakingInfo {\n uint256 stakedAmount;\n uint256 unStakeAt;\n uint256 duration;\n uint256 rewardPerTokenPaid;\n uint256 rewards;\n }\n\n /**\n * @notice Represent duration and multiplier per each stake option.\n * @param duration Staking period in seconds.\n * @param multiplier Token weight\n */\n struct StakeDurationInfo {\n uint256 duration;\n uint256 multiplier;\n }\n\n /// @notice Decimals of multiplier\n uint256 public constant MULTIPLIER_BASIS = 1e4;\n\n /// @notice Stake and Reward token.\n IERC20Upgradeable public stakeRewardToken;\n\n /// @notice Minimal stake duration for perks.\n uint256 public stakeDurationForPerks;\n\n /// @notice Minimal stake amount for perks.\n uint256 public stakeAmountForPerks;\n\n /// @notice Stake durations info array.\n StakeDurationInfo[] public stakeDurationInfos;\n\n /// @notice Duration of the rewards (in seconds).\n uint256 public rewardsDuration;\n\n /// @notice Timestamp of when the rewards finish.\n uint256 public finishAt;\n\n /// @notice Timestamp of the reward updated.\n uint256 public lastUpdateTime;\n\n /// @notice Reward per second(total rewards / duration).\n uint256 public rewardRatePerSec;\n\n /// @notice Reward per token stored, sum of (reward rate * dt * 1e18 / total supply).\n uint256 public rewardPerTokenStored;\n\n /// @notice Total staked amounts.\n uint256 public totalStaked;\n\n // Total staked amounts with multiplier applied\n uint256 public totalWeightedStake;\n\n /// @notice User stakingInfo map, user address => array of the staking info\n mapping(address => StakingInfo[]) public userStakingInfo;\n\n /// @notice Total rewards amount.\n uint256 public totalRewards;\n\n /**\n * @notice Emitted when users stake token\n * @param user User address\n * @param stakeIndex Latest index of user staking pool\n * @param amount Staked amount\n */\n event Staked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users unstake token\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param amount Staked amount\n */\n event Unstaked(address indexed user, uint256 stakeIndex, uint256 amount);\n\n /**\n * @notice Emitted when users claim rewards\n * @param user User address\n * @param stakeIndex User staking pool index\n * @param reward Reward token amount\n */\n event RewardPaid(address indexed user, uint256 stakeIndex, uint256 reward);\n\n /**\n * @notice Emitted when admin add rewards.\n * @param rewardAmount Reward amount added by admin.\n * @param rewardPerSec RewardRatePerSec updated.\n */\n event NotifiedRewardAmount(uint256 rewardAmount, uint256 rewardPerSec);\n\n /**\n * @notice Holds a mapping of addresses that default to the highest staking tier.\n * @dev This is notably used to allow PreMining contracts to benefit from 0%\n * withdrawal fees in L-Tokens contracts, when accounts unlock their funds.\n */\n mapping(address => bool) public highTierAccounts;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract and sets the initial state variables. This is called by the proxy and should only be called once.\n * @dev This function is intended for setting initial values for the contract's state variables.\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param stakeRewardToken_ The address of stake and reward token(LDY token).\n * @param stakeDurationInfos_ Available Staking Durations.\n * @param stakeDurationForPerks_ Minimal staking duration for perks.\n * @param stakeAmountForPerks_ Minimal staking amount for perks.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address stakeRewardToken_,\n StakeDurationInfo[] memory stakeDurationInfos_,\n uint256 stakeDurationForPerks_,\n uint256 stakeAmountForPerks_\n ) public initializer {\n __Base_init(globalOwner_, globalPause_, globalBlacklist_);\n stakeRewardToken = IERC20Upgradeable(stakeRewardToken_);\n uint stakeDurationInfosLength = stakeDurationInfos_.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n stakeDurationInfos.push(stakeDurationInfos_[i]);\n }\n stakeDurationForPerks = stakeDurationForPerks_;\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n // --------------------\n // MUTATIVE FUNCTIONS\n // --------------------\n\n /**\n * @notice Staked tokens cannot be withdrawn during the stakeDuration period and are eligible to claim rewards.\n * @dev Emits a `Staked` event upon successful staking.\n * @param amount The amount of tokens to stake.\n * @param stakeDurationIndex The Index of stakeDurationInfos array.\n */\n function stake(\n uint256 amount,\n uint8 stakeDurationIndex\n ) external nonReentrant whenNotPaused notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(stakeDurationIndex <= stakeDurationInfos.length - 1, \"Invalid staking period\");\n\n _updateReward(address(0), 0);\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[stakeDurationIndex];\n StakingInfo memory stakingInfo = StakingInfo({\n stakedAmount: amount,\n unStakeAt: block.timestamp + stakeDurationInfo.duration,\n duration: stakeDurationInfo.duration,\n rewardPerTokenPaid: rewardPerTokenStored,\n rewards: 0\n });\n\n // check whether account is eligible for benefit from the protocol\n if (stakeDurationInfo.duration >= stakeDurationForPerks && amount >= stakeAmountForPerks) {\n highTierAccounts[_msgSender()] = true;\n }\n\n userStakingInfo[_msgSender()].push(stakingInfo);\n\n uint256 stakeIndex = userStakingInfo[_msgSender()].length - 1;\n uint256 weightedStake = (amount * stakeDurationInfo.multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake += weightedStake;\n totalStaked += amount;\n\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit Staked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Withdraw staked tokens after stakeDuration has passed.\n * @dev Emits a `Unstaked` event upon successful withdrawal.\n * On full withdrawal, userStakingInfo removes stake pool for stakeIndex.\n * @param amount The amount of tokens to withdraw.\n * @param stakeIndex The index of user staking pool\n */\n function unstake(\n uint256 amount,\n uint256 stakeIndex\n ) external nonReentrant notBlacklisted(_msgSender()) {\n require(amount > 0, \"amount = 0\");\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n require(\n block.timestamp >= userStakingInfo[_msgSender()][stakeIndex].unStakeAt,\n \"Cannot unstake during staking period\"\n );\n require(\n amount <= userStakingInfo[_msgSender()][stakeIndex].stakedAmount,\n \"Insufficient unstake amount\"\n );\n\n _updateReward(_msgSender(), stakeIndex);\n\n uint256 multiplier = _getMultiplier(userStakingInfo[_msgSender()][stakeIndex].duration);\n\n uint256 currentWeightedStake = (amount * multiplier) / MULTIPLIER_BASIS;\n totalWeightedStake -= currentWeightedStake;\n\n totalStaked -= amount;\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount -= amount;\n\n // check whether account is eligible for benefit from the protocol\n if (\n userStakingInfo[_msgSender()][stakeIndex].duration >= stakeDurationForPerks &&\n userStakingInfo[_msgSender()][stakeIndex].stakedAmount < stakeAmountForPerks\n ) {\n highTierAccounts[_msgSender()] = false;\n }\n\n // remove staking info from array on full withdrawal\n if (userStakingInfo[_msgSender()][stakeIndex].stakedAmount == 0) {\n _claimReward(_msgSender(), stakeIndex);\n\n userStakingInfo[_msgSender()][stakeIndex] = userStakingInfo[_msgSender()][\n userStakingInfo[_msgSender()].length - 1\n ];\n userStakingInfo[_msgSender()].pop();\n }\n stakeRewardToken.safeTransfer(_msgSender(), amount);\n\n emit Unstaked(_msgSender(), stakeIndex, amount);\n }\n\n /**\n * @notice Claim pending rewards.\n * @dev Emits a `RewardPaid` event upon successful reward claim.\n * @param stakeIndex The index of user staking pool.\n */\n function getReward(uint256 stakeIndex) external nonReentrant notBlacklisted(_msgSender()) {\n require(userStakingInfo[_msgSender()].length >= stakeIndex + 1, \"Invalid stakeIndex\");\n _updateReward(_msgSender(), stakeIndex);\n _claimReward(_msgSender(), stakeIndex);\n }\n\n // --------------------\n // ADMIN CONFIGURATION\n // --------------------\n\n /**\n * @notice Update Rewards Duration.\n * @dev Only callable by owner, and setting available only after rewards period.\n * @param duration New reward duration in seconds.\n */\n function setRewardsDuration(uint256 duration) external onlyOwner {\n require(finishAt < block.timestamp, \"reward duration is not finished\");\n rewardsDuration = duration;\n }\n\n /**\n * @notice Update stakeDurationForPerks\n * @dev Only callable by owner.\n * @param stakeDurationForPerks_ New stakeDurationForPerks.\n */\n function setStakeDurationForPerks(uint256 stakeDurationForPerks_) external onlyOwner {\n stakeDurationForPerks = stakeDurationForPerks_;\n }\n\n /**\n * @notice Update stakeAmountForPerks\n * @dev Only callable by owner.\n * @param stakeAmountForPerks_ New stakeDurationForPerks.\n */\n function setStakeAmountForPerks(uint256 stakeAmountForPerks_) external onlyOwner {\n stakeAmountForPerks = stakeAmountForPerks_;\n }\n\n /**\n * @notice Push stakeDurationInfo\n * @dev Only callable by owner.\n */\n function pushStakeDurationInfo(StakeDurationInfo memory durationInfo) external onlyOwner {\n stakeDurationInfos.push(durationInfo);\n }\n\n /**\n * @notice Notify the contract about the amount of rewards to be distributed and update reward parameters.\n * @dev Only callable by owner.\n * @param amount The amount of reward to be distributed.\n */\n function notifyRewardAmount(uint256 amount) external onlyOwner {\n require(rewardsDuration > 0, \"rewards duration is not set\");\n require(amount > 0, \"amount = 0\");\n\n _updateReward(address(0), 0);\n\n if (block.timestamp >= finishAt) {\n rewardRatePerSec = amount / rewardsDuration;\n } else {\n uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatePerSec;\n rewardRatePerSec = (amount + remainingRewards) / rewardsDuration;\n }\n\n require(rewardRatePerSec > 0, \"reward rate = 0\");\n require(\n rewardRatePerSec <=\n (stakeRewardToken.balanceOf(address(this)) + amount - totalStaked) /\n rewardsDuration,\n \"reward amount > balance\"\n );\n\n finishAt = block.timestamp + rewardsDuration;\n lastUpdateTime = block.timestamp;\n\n totalRewards += amount;\n stakeRewardToken.safeTransferFrom(_msgSender(), address(this), amount);\n\n emit NotifiedRewardAmount(amount, rewardRatePerSec);\n }\n\n // --------------------\n // VIEW FUNCTIONS\n // --------------------\n\n /**\n * @notice Get the last time when rewards were applicable for the specified reward token.\n * @return Timestamp of the most recent rewards calculation.\n */\n function lastTimeRewardApplicable() public view returns (uint256) {\n return _min(finishAt, block.timestamp);\n }\n\n /**\n * @notice Calculate the reward per token for a given reward token.\n * @return Current reward per token.\n */\n function rewardPerToken() public view returns (uint256) {\n if (totalStaked == 0) {\n return rewardPerTokenStored;\n }\n\n return\n rewardPerTokenStored +\n ((rewardRatePerSec * (lastTimeRewardApplicable() - lastUpdateTime) * 1e18) /\n totalWeightedStake);\n }\n\n /**\n * @notice Calculate the user's stake pool earnings\n * @param account Address of the user.\n * @param stakeIndex Index of the stakePool\n * @return Return earned amounts\n */\n function earned(address account, uint256 stakeIndex) public view returns (uint256) {\n StakingInfo memory userInfo = userStakingInfo[account][stakeIndex];\n uint256 multiplier = _getMultiplier(userInfo.duration);\n uint256 weightedAmount = (userInfo.stakedAmount * multiplier) / MULTIPLIER_BASIS;\n uint256 rewardsSinceLastUpdate = ((weightedAmount *\n (rewardPerToken() - userInfo.rewardPerTokenPaid)) / 1e18);\n return rewardsSinceLastUpdate + userInfo.rewards;\n }\n\n /**\n * @notice Get the earned rewards array for a user.\n * @param account Address of the user.\n * @return Return earned rewards array for a user.\n */\n function getEarnedUser(address account) public view returns (uint256[] memory) {\n uint256 numberOfPools = userStakingInfo[account].length;\n uint256[] memory earnedArray = new uint256[](numberOfPools);\n for (uint256 index; index < numberOfPools; index++) {\n earnedArray[index] = earned(account, index);\n }\n return earnedArray;\n }\n\n /**\n * @dev tierOf() function that always return that the given account is not\n * elligible to any LDY staking tier, except if the account is in the\n * highTierAccounts mapping.\n * @param account The account to check the tier of.\n */\n function tierOf(address account) public view returns (uint256 tier) {\n if (highTierAccounts[account]) return 3;\n return 0;\n }\n\n /**\n * @notice Get User Stake Data.\n * @param account The address of user.\n * @return StakingInfo array.\n */\n function getUserStakes(address account) external view returns (StakingInfo[] memory) {\n return userStakingInfo[account];\n }\n\n /**\n * @notice Get StakeDurationInfo.\n * @param index Index of StakeDurationInfos.\n * @return StakeDurationInfo.\n */\n function getStakeDurationInfo(uint256 index) external view returns (StakeDurationInfo memory) {\n require(stakeDurationInfos.length - 1 >= index, \"wrong index\");\n return stakeDurationInfos[index];\n }\n\n /**\n * @notice Send rewards to user.\n * @dev This is private function, called by getReward function.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _claimReward(address account, uint256 stakeIndex) private {\n uint256 reward = userStakingInfo[account][stakeIndex].rewards;\n\n if (reward > 0) {\n userStakingInfo[account][stakeIndex].rewards = 0;\n totalRewards -= reward;\n stakeRewardToken.safeTransfer(account, reward);\n emit RewardPaid(account, stakeIndex, reward);\n }\n }\n\n /**\n * @notice Calculate and update user rewards per stakeIndex.\n * @dev this is private function, called by stake, unstake, getRewards, and notifyRewardAmount functions.\n * @param account The address of user.\n * @param stakeIndex The index of user staking pool.\n */\n function _updateReward(address account, uint256 stakeIndex) private {\n rewardPerTokenStored = rewardPerToken();\n lastUpdateTime = lastTimeRewardApplicable();\n\n if (account != address(0)) {\n userStakingInfo[account][stakeIndex].rewards = earned(account, stakeIndex);\n userStakingInfo[account][stakeIndex].rewardPerTokenPaid = rewardPerTokenStored;\n }\n }\n\n /**\n * @notice Get multiplier from stakeDurationInfo based on duration\n * @param duration Stake Duration\n */\n function _getMultiplier(uint256 duration) private view returns (uint256) {\n uint256 stakeDurationInfosLength = stakeDurationInfos.length;\n for (uint256 i = 0; i < stakeDurationInfosLength; i++) {\n StakeDurationInfo memory stakeDurationInfo = stakeDurationInfos[i];\n if (duration == stakeDurationInfo.duration) {\n return stakeDurationInfo.multiplier;\n }\n }\n return 0;\n }\n\n /**\n * @notice Take minimum value between x and y.\n */\n function _min(uint256 x, uint256 y) private pure returns (uint256) {\n return x <= y ? x : y;\n }\n}\n" + }, + "contracts/src/libs/APRHistory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n/**\n * @title APRHistory\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice This library offers utilities to efficiently maintain the history of an\n * on-chain APR (Annual Percentage Rate) state. Each entry in this history is called\n * a \"checkpoint\".\n *\n * @dev Intuition:\n * Each checkpoint in an APR history consists of two data:\n * - the creation timestamp\n * - the APR at that time\n *\n * Given that reading and writing to storage slots are among the most costly operations\n * in Solidity, this library provides a way to store those data in a way that minimizes\n * the number of used storage slots.\n *\n * Instead of storing each checkpoint in a separate storage slot, this library\n * facilitates the packing of up to 4 checkpoints in a single storage slot.\n *\n * @dev Definitions:\n * - Checkpoint: A record of an APR change\n * - Pack: A collection of 4 checkpoints stored in a single storage slot\n * - History: A dynamic array of packs\n * - Reference: A storage pointer to a checkpoint in the APR history\n * - CheckpointData: An in-memory representation of a checkpoint data\n *\n * @dev Value limitation:\n * This library can accommodate APRs only up to 65.536%. This is however sufficient for\n * APR in LToken contract, which is expected to remain below 10%.\n *\n * @dev For further details, see \"APRHistory\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary APRHistory {\n /**\n * @notice Represents data of a checkpoint extracted from the on-chain history.\n * For on-chain representation see \"Pack\" struct.\n * @param aprUD7x3 APR in UD7x3 format (e.g., 12345 = 12.345%).\n * @param timestamp Timestamp of the checkpoint's creation.\n */\n struct CheckpointData {\n uint16 aprUD7x3; // Allows up to 65.536%\n uint40 timestamp; // Supports dates up to 20/02/36812\n }\n\n /**\n * @notice Represents how APR checkpoints are stored on chain. Each pack can contain\n * the data 4 checkpoints. Packs are then stored in a dynamic array (the history).\n * @param aprsUD7x3 Array of checkpoints' APRs.\n * @param timestamps Array of checkpoints' timestamps.\n * @param cursor Index of the next checkpoint to be written.\n */\n struct Pack {\n uint16[4] aprsUD7x3;\n uint40[4] timestamps;\n uint32 cursor;\n }\n\n /**\n * @notice Represents a storage pointer to a specific checkpoint in the history.\n * @param packIndex Index of the pack the checkpoint belongs to.\n * @param cursorIndex Index of the checkpoint in this pack (between 0 and 3).\n */\n struct Reference {\n uint256 packIndex;\n uint32 cursorIndex;\n }\n\n /**\n * @notice Compares two checkpoints references.\n * @param ref1 The first reference to compare.\n * @param ref2 The second reference to compare.\n * @return Whether the two references points to the same checkpoint.\n */\n function eq(Reference memory ref1, Reference memory ref2) external pure returns (bool) {\n return ref1.packIndex == ref2.packIndex && ref1.cursorIndex == ref2.cursorIndex;\n }\n\n /**\n * @notice Returns the reference of the checkpoint that should come right after the\n * referenced checkpoint in the APR history.\n * @param ref The reference to be incremented.\n * @return The incremented reference.\n */\n function incrementReference(Reference memory ref) public pure returns (Reference memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L1\");\n\n // If the given ref is the last slot in its pack, return ref of next pack's first slot\n if (ref.cursorIndex == 3) return Reference(ref.packIndex + 1, 0);\n //\n // Else, return ref of next slot in current pack\n else return Reference(ref.packIndex, ref.cursorIndex + 1);\n }\n\n /**\n * @notice Extracts checkpoint data from a given reference and in APR history.\n * @param self The APR history to extract the checkpoint from.\n * @param ref The reference of the checkpoint data to extract.\n * @return The extracted checkpoint's data.\n */\n function getDataFromReference(\n Pack[] storage self,\n Reference memory ref\n ) public view returns (CheckpointData memory) {\n // Ensure cursor index of the given ref is within valid range [0, 3]\n require(ref.cursorIndex <= 3, \"L2\");\n\n // Ensure pack index of the given ref exists in history\n require(ref.packIndex < self.length, \"L3\");\n\n // Retrieve pack data from history\n Pack memory pack = self[ref.packIndex];\n\n // Ensure cursor index of the given ref has been written\n require(ref.cursorIndex < pack.cursor, \"L4\");\n\n // Build and return the checkpoint data\n return\n CheckpointData({\n aprUD7x3: pack.aprsUD7x3[ref.cursorIndex],\n timestamp: pack.timestamps[ref.cursorIndex]\n });\n }\n\n /**\n * @notice Retrieves the reference to the most recently added checkpoint in the APR history.\n * @param self The history to extract the reference from.\n * @return The reference of the latest checkpoint.\n */\n function getLatestReference(Pack[] storage self) public view returns (Reference memory) {\n // Ensure the given history is not empty\n require(self.length != 0, \"L5\");\n\n // Retrieve latest pack's index and cursor\n uint256 packIndex = self.length - 1;\n uint32 packCursor = self[packIndex].cursor;\n\n // If this is the first pack ever, ensure it is not empty\n if (packIndex == 0) require(packCursor != 0, \"L6\");\n\n // If the pack is empty, return ref of previous pack's latest slot\n if (packCursor == 0) return Reference(packIndex - 1, 3);\n //\n // Else, return ref of previous slot in current pack\n else return Reference(packIndex, packCursor - 1);\n }\n\n /**\n * @notice Appends a new empty pack to the end of the given APR history array.\n * @param self The APR history to append an empty to.\n */\n function newBlankPack(Pack[] storage self) internal {\n // If history is not empty, ensure the latest pack is full\n require(self.length == 0 || getLatestReference(self).cursorIndex == 3, \"L7\");\n\n // Push a new blank pack to the history array\n self.push(\n Pack({\n aprsUD7x3: [uint16(0), uint16(0), uint16(0), uint16(0)],\n timestamps: [uint40(0), uint40(0), uint40(0), uint40(0)],\n cursor: 0\n })\n );\n }\n\n /**\n * @notice Write a new APR checkpoint at the end of the given history array.\n * @param self The array of packs to write the new checkpoint to.\n * @param aprUD7x3 The new APR in UD7x3 format.\n */\n function setAPR(Pack[] storage self, uint16 aprUD7x3) external {\n // Determine the reference where the new checkpoint should be written\n Reference memory newRef = self.length == 0\n ? Reference(0, 0)\n : incrementReference(getLatestReference(self));\n\n // If pack to be written doesn't exist yet, push a new blank pack in history\n if (newRef.packIndex >= self.length) newBlankPack(self);\n\n // Retrieve the pack where the new checkpoint will be stored\n Pack memory pack = self[newRef.packIndex];\n\n // Add new checkpoint's data to the pack\n pack.aprsUD7x3[newRef.cursorIndex] = aprUD7x3;\n pack.timestamps[newRef.cursorIndex] = uint40(block.timestamp);\n\n // Increment the pack's cursor\n pack.cursor++;\n\n // Write the updated pack in storage\n self[newRef.packIndex] = pack;\n }\n\n /**\n * @notice Retrieves the APR of the latest checkpoint written in the APR history.\n * @param self The history array to read APR from.\n * @return The latest checkpoint's APR.\n */\n function getAPR(Pack[] storage self) public view returns (uint16) {\n // Retrieve the latest checkpoint data\n Reference memory ref = getLatestReference(self);\n CheckpointData memory data = getDataFromReference(self, ref);\n\n // Return the latest checkpoint's APR\n return data.aprUD7x3;\n }\n}\n" + }, + "contracts/src/libs/SUD.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @title SUD\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice SUD serves as an intermediary number format for calculations within this\n * codebase. It ensures consistency and reduces precision losses. This library\n * facilitates conversions between various number formats and the SUD format.\n *\n * @dev Intuition:\n * This codebase employs the UD (unsigned decimal fixed-point numbers) format to\n * represent both percentage rates and tokens amounts.\n *\n * Rates are expressed in UD7x3 format, whereas the format for tokens amounts depends on\n * the decimals() value of the involved tokens.\n *\n * Three challenges arise from this:\n * 1) To compute values together, it's essential that they are in the same format\n * 2) Calculations involving consecutive divisions on UD numbers lead to accumulated\n * precision loss (because division shrinks). A common approach is to scale up and\n * down values by a few decimals before and after performing calculations.\n * 3) Given that rates use the UD7x3 format, if we decided to scale them to and from\n * the number of decimals of the involved token, 1 to 3 of the rates' decimals would\n * be shrunk in case token's decimals number is in [0, 2].\n *\n * To address these challenges, this library provides the SUD format, which acts as a\n * consistent and scaled intermediate format to perform calculations.\n *\n * SUD is an acronym for either \"Scaled UD\" or \"Safe UD\".\n *\n * @dev Definitions:\n * - Integer: A number without fractional part, e.g., block.timestamp\n * - UD: A decimal unsigned fixed-point number. The \"UD\" notation is inspired from\n * libraries like [prb-math](https://github.com/PaulRBerg/prb-math/)\n * - Amount: A token amount. A UD with an unknown repartition of digits between integral\n * and fractional parts (as token amounts have variable decimal numbers)\n * - Rate: A percentage rate. An UD with 7 integral digits and 3 fractional ones (= UD7x3)\n * - SUD: An intermediate format to perform calculations involving Rates and Amounts. A UD\n * with 3 more decimals than the involved UD with the highest decimals number. As\n * rates are represented by UD7x3, a SUD number has at least 6 decimals (3+3) and\n * so ranges from UD71x6 to UD0x77 formats.\n *\n * @dev A conversion library:\n * This library provides utilities to perform the following conversions:\n * - Amount <--> SUD\n * - Rate (UD7x3) <--> SUD\n * - Integer <--> SUD\n *\n * @dev Why scaling by 3 decimals?\n * - It provides an adequate degree of precision for this codebase,\n * - It enables the conversion of a UD7x3 rate to SUD format by merely scaling it up by\n * the involved token's decimal number, so is gas efficient.\n *\n * @dev Why internal functions?\n * The functions of this library are not set to external because incorporating them\n * directly into contracts is more gas-efficient. Given their minimal size and frequent\n * usage in the InvestUpgradeable, LDYStaking, and LToken contracts, any bytecode savings\n * from making them external are negated by the additional bytecode required for external\n * calls to this library. This can be observed by comparing the output of `bun cc:size`\n * when those functions's visibility is set to external or internal.\n *\n * @dev Precision warning:\n * While this library mitigates precision loss during calculations on UD numbers, it's\n * important to note that tokens with lower decimal counts and supply inherently suffer\n * more from precision loss. Conversely, tokens with higher decimal counts and supply\n * will experience less precision loss.\n *\n * @dev For further details, see \"SUD\" section of whitepaper.\n * @custom:security-contact security@ledgity.com\n */\nlibrary SUD {\n /**\n * @notice Retrieves decimals number of the given ERC20 contract address.\n * @param tokenAddress The address to retrieve decimals number from.\n * @return decimals The decimals number of the given ERC20 contract address.\n */\n function decimalsOf(address tokenAddress) internal view returns (uint256 decimals) {\n return IERC20MetadataUpgradeable(tokenAddress).decimals();\n }\n\n /**\n * @notice Convert a given token amount into SUD format.\n * @param nAmount The token amount to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The amount in SUD format\n */\n function fromAmount(uint256 nAmount, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nAmount * 10 ** (6 - decimals);\n\n // Else return a number with decimals+3 fractional digits\n return nAmount * 10 ** 3;\n }\n\n /**\n * @notice Convert a given SUD number into token amount format.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nAmount The number in amount format\n */\n function toAmount(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nAmount) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** (6 - decimals);\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** 3;\n }\n\n /**\n * @notice Converts a given UD7x3 rate into SUD format.\n * @param nUD7x3 The UD7x3 rate to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The rate in SUD format.\n */\n function fromRate(uint256 nUD7x3, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return nUD7x3 * 10 ** 3;\n\n // Else, return a number with decimals+3 fractional digits\n return nUD7x3 * 10 ** decimals;\n }\n\n /**\n * @notice Converts a given SUD number into a UD7x3 rate.\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nUD7x3 The number in UD7x3 rate format.\n */\n function toRate(uint256 nSUD, uint256 decimals) internal pure returns (uint256 nUD7x3) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 3;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** decimals;\n }\n\n /**\n * @notice Converts a given integer into SUD format.\n * @param n The integer to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return nSUD The integer in SUD format.\n */\n function fromInt(uint256 n, uint256 decimals) internal pure returns (uint256 nSUD) {\n // If token decimals < 3, return a UD71x6 number\n if (decimals < 3) return n * 10 ** 6;\n\n // Else, return a number with decimals+3 fractional digits\n return n * 10 ** (decimals + 3);\n }\n\n /**\n * @notice Converts a given SUD number as an integer (all decimals shrinked).\n * @param nSUD The SUD number to convert.\n * @param decimals The decimals number of the involved ERC20 token.\n * @return n The SUD number as an integer.\n */\n function toInt(uint256 nSUD, uint256 decimals) internal pure returns (uint256 n) {\n // If token decimals < 3, convert from a UD71x6 number\n if (decimals < 3) return nSUD / 10 ** 6;\n\n // Else, convert from a number with decimals+3 fractional digits\n return nSUD / 10 ** (decimals + 3);\n }\n}\n" + }, + "contracts/src/LToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n// Contracts\nimport {ERC20WrapperUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20WrapperUpgradeable.sol\";\nimport \"./abstracts/base/ERC20BaseUpgradeable.sol\";\nimport {InvestUpgradeable} from \"./abstracts/InvestUpgradeable.sol\";\nimport {LDYStaking} from \"./LDYStaking.sol\";\n\n// Libraries\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {SUD} from \"./libs/SUD.sol\";\n\n// Interfaces\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {ITransfersListener} from \"./interfaces/ITransfersListener.sol\";\n\n/**\n * @title LToken\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n *\n * @notice Main contract of the Ledgity Yield protocol. It powers every L-Token (i.e.,\n * investment pools backed by RWA). An L-Token is an ERC20 wrapper around a stablecoin.\n * As soon as a wallet holds some L-Tokens, it starts receiving rewards in\n * the form of additional L-Tokens, which are auto-compounded over time.\n *\n * @dev Definitions:\n * - Deposit: Swap of underlying tokens for L-Tokens (1:1 ratio).\n * - Withdrawal: Swap of L-Tokens for underlying tokens (1:1 ratio, minus applicable fees).\n * - Instant: Processed immediately.\n * - Request: Queued for later processing.\n * - Big Request: A requested withdrawal exceeding half of the retention rate.\n * - (Withdrawal) queue: A list of all requested withdrawals sorted by priority.\n * - Request ID: The index of a withdrawal request in the queue array.\n * - Retention rate: Maximum fraction of underlying tokens TVL the contract can retain.\n * - Fees Rate: Percentage of fees applied to successful withdrawals.\n * - Usable underlyings: Amount of underlying tokens that have been deposited through\n * expected ways and are so considered safe to use by the contract.\n * - Transfers listeners: External contracts listening on L-Tokens transfers.\n * - Fund wallet: Wallet managed by the Ledgity's financial team.\n * - Withdrawer wallet: Managed by an off-chain server to automate withdrawal request\n * processing.\n *\n * Note that words between parenthesis are sometimes omitted for brevity.\n *\n * @dev Deployment notice:\n * This contract can safely receive funds immediately after initialization. (i.e., there\n * is no way for funds to be sent to non-owned addresses). It is, however, recommended to\n * replace ASAP owner and fund wallets with multi-sig wallets.\n *\n * @dev For further details, see \"LToken\" section of whitepaper.\n * @custom:oz-upgrades-unsafe-allow external-library-linking\n * @custom:security-contact security@ledgity.com\n */\ncontract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @dev Represents type of actions triggering ActivityEvent events.\n enum Action {\n Deposit,\n Withdraw\n }\n\n /// @dev Represents different status of actions triggering ActivityEvent events.\n enum Status {\n Queued,\n Cancelled,\n Success,\n Moved\n }\n\n /**\n * @notice Represents a withdrawal request in the queue.\n * @dev A request fits in a single storage slot (32 bytes).\n * @param account The account that initiated the request.\n * @param amount The amount of underlying tokens requested.\n */\n struct WithdrawalRequest {\n address account; // 20 bytes\n uint96 amount; // 12 bytes\n }\n\n /// @notice Upper limit of retention rate.\n uint32 private constant MAX_RETENTION_RATE_UD7x3 = 10 * 10 ** 3; // 10%\n\n /// @notice Upper limit of fees rate.\n uint32 private constant MAX_FEES_RATE_UD7x3 = 20 * 10 ** 3; // 20%\n\n /// @notice Used in activity events to represent the absence of request ID.\n int256 private constant NO_ID = -1;\n\n /// @notice Holds a reference to the LDYStaking contract.\n LDYStaking public ldyStaking;\n\n /// @notice Holds address of withdrawer wallet (managed by withdrawal server).\n address payable public withdrawer;\n\n /// @notice Holds address of fund wallet (managed by Ledgity financial team).\n address public fund;\n\n /// @notice Holds the withdrawal fees rate in UD7x3 format (e.g., 350 = 0.350%).\n uint32 public feesRateUD7x3;\n\n /// @notice Holds the retention rate in UD7x3 format.\n uint32 public retentionRateUD7x3;\n\n /// @notice Holds the amount of withdrawal fees not yet claimed by contract's owner.\n uint256 public unclaimedFees;\n\n /// @notice Holds the amount of L-Tokens currently in the withdrawal queue.\n uint256 public totalQueued;\n\n /**\n * @notice Holds the amount of underlying tokens considered as usable by the contract.\n * @dev Are usable, only underlying tokens deposit through deposit() or fund() functions.\n */\n uint256 public usableUnderlyings;\n\n /// @notice Holds an ordered list of active withdrawal requests.\n WithdrawalRequest[] public withdrawalQueue;\n\n /// @notice Holds the index of the next withdrawal request to process in the queue.\n uint256 public withdrawalQueueCursor;\n\n /**\n * @notice Holds a list of all currently frozen withdrawal requests.\n * @dev If a request emitter as been blacklisted, its request is moved here to prevent\n * it from blocking the queue.\n */\n WithdrawalRequest[] public frozenRequests;\n\n /**\n * @notice Holds a list of contracts' references that are listening to L-Tokens transfers.\n * @dev onLTokenTransfer() functions of those contracts will be called on each transfer.\n */\n ITransfersListener[] public transfersListeners;\n\n /**\n * @notice Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet.\n */\n uint256 public withdrwalFeeInEth;\n\n /**\n * @notice Emitted to inform listeners about a change in the contract's TVL.\n * @dev TVL = realTotalSupply()\n * @param newTVL The new TVL of the contract.\n */\n event TVLChangeEvent(uint256 newTVL);\n\n /**\n * @notice Emitted to inform listerners about an activity related to deposits and withdrawals.\n * @param id ID of the involved withdrawal request or NO_ID (-1) if not applicable.\n * @param account The account involved in the activity.\n * @param action The type of activity.\n * @param amount The amount of underlying tokens involved in the activity.\n * @param newStatus The new status of the activity.\n * @param newId The new ID of the request if it has been moved in the queue.\n */\n event ActivityEvent(\n int256 indexed id,\n address indexed account,\n Action indexed action,\n uint256 amount,\n uint256 amountAfterFees,\n Status newStatus,\n int256 newId\n );\n\n /**\n * @notice Emitted to inform listeners that some rewards have been minted.\n * @param account The account that received the rewards.\n * @param balanceBefore The balance of the account before the minting.\n * @param rewards The amount of minted rewards.\n */\n event MintedRewardsEvent(address indexed account, uint256 balanceBefore, uint256 rewards);\n\n /// @notice Reverts if the function caller is not the withdrawer wallet.\n modifier onlyWithdrawer() {\n require(_msgSender() == withdrawer, \"L39\");\n _;\n }\n\n /// @notice Reverts if the function caller is not the fund wallet.\n modifier onlyFund() {\n require(_msgSender() == fund, \"L40\");\n _;\n }\n\n /**\n * @notice Initializer function of the contract. It replaces the constructor()\n * function in the context of upgradeable contracts.\n * @dev See: https://docs.openzeppelin.com/contracts/4.x/upgradeable\n * @param globalOwner_ The address of the GlobalOwner contract.\n * @param globalPause_ The address of the GlobalPause contract.\n * @param globalBlacklist_ The address of the GlobalBlacklist contract.\n * @param underlyingToken The address of the underlying stablecoin ERC20 token.\n */\n function initialize(\n address globalOwner_,\n address globalPause_,\n address globalBlacklist_,\n address ldyStaking_,\n address underlyingToken\n ) public initializer {\n // Initialize ERC20 base.\n string memory underlyingSymbol = IERC20MetadataUpgradeable(underlyingToken).symbol();\n __ERC20Base_init(\n globalOwner_,\n globalPause_,\n globalBlacklist_,\n string(abi.encodePacked(\"Ledgity \", underlyingSymbol)),\n string(abi.encodePacked(\"L\", underlyingSymbol))\n );\n\n // IMPORTANT: Below calls must not be restricted to owner at any point.\n // This is because the GlobalOwner contract may not be a fresh one, and so\n // the contract deployer may not be the owner anymore after ERC20Base init.\n\n // Initialize other parents contracts.\n __ERC20Wrapper_init(IERC20Upgradeable(underlyingToken));\n __Invest_init_unchained(address(this));\n\n // Set LDYStaking contract\n ldyStaking = LDYStaking(ldyStaking_);\n\n // Set initial withdrawal fees rate to 0.3%\n feesRateUD7x3 = 300;\n\n // Set initial retention rate to 10%\n retentionRateUD7x3 = 10_000;\n\n // Default withdrawer and fund wallet to contract owner address. This prevents\n // any loss of funds if a deposit/withdrawal is made before those are manually set.\n withdrawer = payable(owner());\n fund = payable(owner());\n\n // Set initial withdrwalFeeInEth\n withdrwalFeeInEth = 0.00075 * 1e18;\n }\n\n /**\n * @notice Required override of decimals() which is implemented by both\n * ERC20Upgradeable and ERC20WrapperUpgradeable parent contracts.\n * @dev The ERC20WrapperUpgradeable version is preferred because it mirrors the\n * decimals amount of the underlying stablecoin token.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function decimals()\n public\n view\n override(ERC20Upgradeable, ERC20WrapperUpgradeable)\n returns (uint8)\n {\n return ERC20WrapperUpgradeable.decimals();\n }\n\n /**\n * @notice Required override of paused() which is implemented by both\n * GlobalPausableUpgradeable and ERC20BaseUpgradeable parent contracts.\n * @dev Both version are the same as ERC20BaseUpgradeable.paused() mirrors\n * GlobalPausableUpgradeable.paused(), so a random one is chosen.\n * @inheritdoc GlobalPausableUpgradeable\n */\n function paused()\n public\n view\n virtual\n override(GlobalPausableUpgradeable, ERC20BaseUpgradeable)\n returns (bool)\n {\n return GlobalPausableUpgradeable.paused();\n }\n\n /**\n * @notice Updates the current withdrawal fee rate.\n * @param feesRateUD7x3_ The new withdrawal fee rate in UD7x3 format.\n */\n function setFeesRate(uint32 feesRateUD7x3_) public onlyOwner {\n require(feesRateUD7x3_ <= MAX_FEES_RATE_UD7x3, \"L88\");\n feesRateUD7x3 = feesRateUD7x3_;\n }\n\n /**\n * @notice Updates the current withdrawalFeeInETH.\n * @param withdrwalFeeInEth_ The new withdrawalFee in ETH.\n */\n function setWithdrwalFeeInEth(uint32 withdrwalFeeInEth_) public onlyOwner {\n require(withdrwalFeeInEth <= MAX_FEES_RATE_UD7x3, \"L88\");\n withdrwalFeeInEth = withdrwalFeeInEth_;\n }\n\n /**\n * @notice Updates the current underlying token retention rate.\n * @dev The retention rate is capped at 10%, which ensures that no more than 10% of\n * deposited assets will ever be exposed in this contract (reduces attack surface).\n * @param retentionRateUD7x3_ The new retention rate in UD7x3 format.\n */\n function setRetentionRate(uint32 retentionRateUD7x3_) public onlyOwner {\n require(retentionRateUD7x3_ <= MAX_RETENTION_RATE_UD7x3, \"L41\");\n retentionRateUD7x3 = retentionRateUD7x3_;\n }\n\n /**\n * @notice Updates the address of LDYStaking contract.\n * @param ldyStakingAddress The address of the new LDYStaking contract.\n */\n function setLDYStaking(address ldyStakingAddress) public onlyOwner {\n ldyStaking = LDYStaking(ldyStakingAddress);\n }\n\n /**\n * @notice Updates the address of the withdrawer wallet.\n * @param withdrawer_ The address of the new withdrawer wallet.\n */\n function setWithdrawer(address payable withdrawer_) public onlyOwner {\n // Ensure address is not the zero address (pre-processing fees would be lost else)\n require(withdrawer_ != address(0), \"L63\");\n\n // Set new withdrawer wallet's address\n withdrawer = withdrawer_;\n }\n\n /**\n * @notice Updates the address of the fund wallet.\n * @param fund_ The address of the new fund wallet.\n */\n function setFund(address payable fund_) public onlyOwner {\n // Ensure address is not the zero address (deposited tokens would be lost else)\n require(fund_ != address(0), \"L64\");\n\n // Set new fund wallet's address\n fund = fund_;\n }\n\n /**\n * @notice Adds a new contract to the L-Token transfers list.\n * @dev Each time a transfer occurs, the onLTokenTransfer() function of the\n * specified contract will be called.\n * @dev IMPORTANT SECURITY NOTE: This method is not intended to be used with\n * contracts that are not owned by the Ledgity team.\n * @param listenerContract The address of the new transfers listener contract.\n */\n function listenToTransfers(address listenerContract) public onlyOwner {\n transfersListeners.push(ITransfersListener(listenerContract));\n }\n\n /**\n * @notice Removes a contract from the L-Token transfers list.\n * @dev The onLTokenTransfer() function of the specified contract will not be called\n * anymore each time a L-Token transfer occurs.\n * @param listenerContract The address of the listener contract.\n */\n function unlistenToTransfers(address listenerContract) public onlyOwner {\n // Find index of listener contract in transferListeners array\n int256 index = -1;\n uint256 transfersListenersLength = transfersListeners.length;\n for (uint256 i = 0; i < transfersListenersLength; i++) {\n if (address(transfersListeners[i]) == listenerContract) {\n index = int256(i);\n break;\n }\n }\n\n // Revert if given contract wasn't listening to transfers\n require(index > -1, \"L42\");\n\n // Else, remove transfers listener contract from listeners array\n transfersListeners[uint256(index)] = transfersListeners[transfersListenersLength - 1];\n transfersListeners.pop();\n }\n\n /**\n * @notice Retrieves the amount of given account's not yet minted rewards.\n * @dev This is a public implementation of InvestUpgradeable_rewardsOf(). In the\n * context of LToken, this function returns the amount of rewards that have not been\n * distributed/minted yet to the specified account.\n * @dev This is particularly useful for off-chain services to display charts and\n * statistics, as seen in the Ledgity Yield's frontend.\n * @param account The account to check the unminted rewards of.\n * @return The amount of account's unminted rewards.\n */\n function unmintedRewardsOf(address account) public view returns (uint256) {\n return _rewardsOf(account, true);\n }\n\n /**\n * @notice Retrieves the \"real\" balance of an account, i.e., excluding its not yet\n * minted/distributed rewards.\n * @param account The account to check the real balance of.\n * @return The real balance of the account.\n */\n function realBalanceOf(address account) public view returns (uint256) {\n return super.balanceOf(account);\n }\n\n /**\n * @notice Retrieves the total balance of L-Tokens that belong to the account.\n * @dev This is an oOverride of ERC20Upgradeable.balanceOf() that rewards that have\n * not been yet minted to the specified account.\n * @param account The account to check the total balance of.\n * @return The total balance of the account.\n */\n function balanceOf(address account) public view override returns (uint256) {\n return realBalanceOf(account) + unmintedRewardsOf(account);\n }\n\n /**\n * @notice Returns the \"real\" amount of existing L-Tokens, i.e., excluding not yet\n * minted withdrawal fees and L-Tokens currently in the withdrawal queue.\n * @return The real total supply of L-Tokens.\n */\n function realTotalSupply() public view returns (uint256) {\n return super.totalSupply();\n }\n\n /**\n * @notice Retrives the total supply of L-Tokens, including not yet minted withdrawal\n * fees and L-Tokens currently in the withdrawal queue.\n * @return The total supply of L-Tokens.\n */\n function totalSupply() public view override returns (uint256) {\n return realTotalSupply() + totalQueued + unclaimedFees;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address.\n * @dev This override of RecoverableUpgradeable.recoverERC20() prevents the recovered\n * token from being the underlying token.\n * @inheritdoc RecoverableUpgradeable\n */\n function recoverERC20(address tokenAddress, uint256 amount) public override onlyOwner {\n // Ensure the token is not the underlying token\n require(tokenAddress != address(underlying()), \"L43\");\n\n // Proceed to recovery\n super.recoverERC20(tokenAddress, amount);\n }\n\n /**\n * @notice Recovers underlying tokens accidentally sent to the contract.\n * @dev To prevent owner from being able to drain the contract, this function only\n * allows recovering \"unusable\" underlying tokens, i.e., tokens that have not been\n * sent through fund() or deposit() functions.\n */\n function recoverUnderlying() external onlyOwner {\n // Compute the recoverable amount by taking the difference between the contract's\n // balance and the amount of usable underlying tokens\n uint256 recoverableAmount = underlying().balanceOf(address(this)) - usableUnderlyings;\n\n // Revert if there is nothing to recover\n require(recoverableAmount > 0, \"L44\");\n\n // Else, proceed to underlying tokens recovery\n super.recoverERC20(address(underlying()), recoverableAmount);\n }\n\n /**\n * @notice Retrieves the amount of underlying tokens invested by the given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract. In\n * LToken contract, the investment of an account is equal to its real balance.\n * @inheritdoc InvestUpgradeable\n */\n function _investmentOf(address account) internal view override returns (uint256) {\n return realBalanceOf(account);\n }\n\n /**\n * @notice Distributes a specified amount of rewards (in L-Tokens) to a given account.\n * @dev Implementing this function is required by the InvestUpgradeable contract so\n * it can distribute rewards to accounts before each period reset.\n * @dev InvestUpgradeable contract already ensure that amount > 0.\n * @inheritdoc InvestUpgradeable\n */\n function _distributeRewards(address account, uint256 amount) internal override returns (bool) {\n // Inform listeners of the rewards minting\n emit MintedRewardsEvent(account, realBalanceOf(account), amount);\n\n // Mint L-Tokens rewards to account\n _mint(account, amount);\n\n // Return true indicating to InvestUpgradeable that the rewards have been distributed\n return true;\n }\n\n /**\n * @notice Override of ERC20._beforeTokenTransfer() to integrate with InvestUpgradeable.\n * @dev This overriden version ensure that _beforeInvestmentChange() hook is properly\n * called each time an account's balance is going to change.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already included in ERC20BaseUpgradeable._beforeTokenTransfer().\n * @inheritdoc ERC20BaseUpgradeable\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override(ERC20Upgradeable, ERC20BaseUpgradeable) {\n ERC20BaseUpgradeable._beforeTokenTransfer(from, to, amount);\n\n // Invoke _beforeInvestmentChange() hook for non-zero accounts\n if (from != address(0)) _beforeInvestmentChange(from, true);\n if (to != address(0)) _beforeInvestmentChange(to, true);\n }\n\n /**\n * @notice Override of ERC20._afterTokenTransfer() to notify all transfers listeners.\n * @dev This overriden version will trigger onLTokenTransfer() functions of all\n * transfers listeners.\n * @dev Note: whenNotPaused and notBlacklisted modifiers are not set as they are\n * already checked in _beforeTokenTransfer().\n * @inheritdoc ERC20Upgradeable\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\n super._afterTokenTransfer(from, to, amount);\n\n // If some L-Token have been burned/minted, inform listeners of a TVL change\n if (from == address(0) || to == address(0)) emit TVLChangeEvent(totalSupply());\n\n // Trigger onLTokenTransfer() functions of all the transfers listeners\n for (uint256 i = 0; i < transfersListeners.length; i++) {\n transfersListeners[i].onLTokenTransfer(from, to, amount);\n }\n }\n\n /**\n * @notice Computes the maximum amount of underlying tokens that should be retained\n * by the contract (based on retention rate).\n * @return amount The expected amount of retained underlying tokens.\n */\n function getExpectedRetained() public view returns (uint256 amount) {\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert totalSupply and retentionRate to SUD\n uint256 totalSupplySUD = SUD.fromAmount(totalSupply(), d);\n uint256 retentionRateSUD = SUD.fromRate(retentionRateUD7x3, d);\n\n // Compute and return expected retained amount\n uint256 expectedRetainedSUD = (totalSupplySUD * retentionRateSUD) / SUD.fromInt(100, d);\n return SUD.toAmount(expectedRetainedSUD, d);\n }\n\n /// @notice Transfers underlying tokens exceeding the retention rate to the fund wallet.\n function _transferExceedingToFund() internal {\n // Retrieve the expected amount retained\n uint256 expectedRetained = getExpectedRetained();\n\n // If usable underlyings are less than or equal to expected retained, return\n if (usableUnderlyings <= expectedRetained) return;\n\n // Else, exceeding amount is equal to difference between those values\n uint256 exceedingAmount = usableUnderlyings - expectedRetained;\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= exceedingAmount;\n\n // Transfer the exceeding amount to the fund wallet\n underlying().safeTransfer(fund, exceedingAmount);\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.withdrawTo() that reverts.\n * Use instantWithdrawal() or requestWithdrawal() functions instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function withdrawTo(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L45\");\n }\n\n /**\n * @notice Override of ERC20WrapperUpgradeable.depositFor() that reverts.\n * Use deposit() function instead.\n * @inheritdoc ERC20WrapperUpgradeable\n */\n function depositFor(address account, uint256 amount) public pure override returns (bool) {\n account; // Silence unused variable compiler warning\n amount;\n revert(\"L46\");\n }\n\n /**\n * @notice Allows exchanging some underlying tokens for the same amount of L-Tokens.\n * @param amount The amount of underlying tokens to deposit.\n */\n function deposit(uint256 amount) public whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough underlying tokens to deposit\n require(underlying().balanceOf(_msgSender()) >= amount, \"L47\");\n\n // Update usable underlyings balance accordingly\n usableUnderlyings += amount;\n\n // Inform listeners of the deposit activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Deposit,\n amount,\n amount,\n Status.Success,\n NO_ID\n );\n\n // Receive underlying tokens and mint L-Tokens to the account in a 1:1 ratio\n super.depositFor(_msgSender(), amount);\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Computes fees and net withdrawn amount for a given account withdrawing a\n * given amount.\n * @param account The account initiating the withdrawal.\n * @param amount The amount of the withdrawal.\n */\n function getWithdrawnAmountAndFees(\n address account,\n uint256 amount\n ) public view returns (uint256 withdrawnAmount, uint256 fees) {\n // If the account is eligible to staking tier 2, no fees are applied\n if (ldyStaking.tierOf(account) >= 2) return (amount, 0);\n\n // Cache invested token's decimals number\n uint256 d = SUD.decimalsOf(address(invested()));\n\n // Convert amount and fees rate to SUD\n uint256 amountSUD = SUD.fromAmount(amount, d);\n uint256 feesRateSUD = SUD.fromRate(feesRateUD7x3, d);\n\n // Compute fees and withdrawn amount (initial amount minus fees)\n uint256 feesSUD = (amountSUD * feesRateSUD) / SUD.fromInt(100, d);\n fees = SUD.toAmount(feesSUD, d);\n withdrawnAmount = amount - fees;\n }\n\n /**\n * @notice Allows instaneously exchanging a given amount of L-Tokens for the same\n * amount of underlying tokens. It will fail if the contract currently doesn't hold\n * enough underlying tokens to cover the withdrawal.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestWithdrawal() function otherwise.\n * @param amount The amount L-Tokens to withdraw.\n */\n function instantWithdrawal(uint256 amount) external whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L48\");\n\n // Can the contract cover this withdrawal plus all already queued requests?\n bool cond1 = totalQueued + amount <= usableUnderlyings;\n\n // Is caller eligible to staking tier 2 and the contract can cover this withdrawal?\n bool cond2 = ldyStaking.tierOf(_msgSender()) >= 2 && amount <= usableUnderlyings;\n\n // Revert if conditions are not met for the withdrawal to be processed instantaneously\n if (!(cond1 || cond2)) revert(\"L49\");\n\n // Else, retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(_msgSender(), amount);\n\n // Increase unclaimed fees amount accordingly\n unclaimedFees += fees;\n\n // Decrease usable underlyings balance accordingly\n usableUnderlyings -= withdrawnAmount;\n\n // Inform listeners of this instant withdrawal activity event\n emit ActivityEvent(\n NO_ID,\n _msgSender(),\n Action.Withdraw,\n amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Burn withdrawal fees from the account\n _burn(_msgSender(), fees);\n\n // Burn account's withdrawn L-Tokens and transfer to it underlying tokens in a 1:1 ratio\n super.withdrawTo(_msgSender(), withdrawnAmount);\n }\n\n /**\n * @notice Allows requesting the exchange of a given amount of L-Tokens for the same\n * amount of underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n * @param amount The amount L-Tokens to withdraw.\n */\n function requestWithdrawal(\n uint256 amount\n ) public payable whenNotPaused notBlacklisted(_msgSender()) {\n // Ensure the account has enough L-Tokens to withdraw\n require(amount <= balanceOf(_msgSender()), \"L53\");\n\n // Ensure the requested amount doesn't overflow uint96\n require(amount <= type(uint96).max, \"L54\");\n\n // Ensure the sender attached the pre-paid processing gas fees\n require(msg.value == withdrwalFeeInEth, \"L55\");\n\n // Create withdrawal request data\n WithdrawalRequest memory request = WithdrawalRequest({\n account: _msgSender(),\n amount: uint96(amount)\n });\n\n // Will hold the request ID\n uint256 requestId;\n\n // Append request to the withdrawal queue:\n // - At the beginning, if account is eligible to staking tier 2 and cursor is not 0\n if (ldyStaking.tierOf(_msgSender()) >= 2 && withdrawalQueueCursor > 0) {\n withdrawalQueueCursor--;\n requestId = withdrawalQueueCursor;\n withdrawalQueue[requestId] = request;\n }\n // - At the end else\n else {\n withdrawalQueue.push(request);\n requestId = withdrawalQueue.length - 1;\n }\n\n // Increase total amount queued accordingly\n totalQueued += amount;\n\n // Inform listeners of this new queued withdrawal activity event\n emit ActivityEvent(\n int256(requestId),\n _msgSender(),\n Action.Withdraw,\n amount,\n amount,\n Status.Queued,\n NO_ID\n );\n\n // Burn withdrawal L-Tokens amount from account's balance\n _burn(_msgSender(), amount);\n\n // Forward pre-paid processing gas fees to the withdrawer wallet\n (bool sent, ) = withdrawer.call{value: msg.value}(\"\");\n require(sent, \"L56\");\n }\n\n /**\n * @notice Processes queued withdrawal requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n * @dev For further details, see \"LToken > Withdrawals\" section of whitepaper.\n */\n function processQueuedRequests() external onlyWithdrawer whenNotPaused {\n // Accumulators variables, will be written on-chain after the loop\n uint256 cumulatedFees = 0;\n uint256 cumulatedWithdrawnAmount = 0;\n uint256 nextRequestId = withdrawalQueueCursor;\n\n // Cache queue length to avoid multiple SLOADs and avoid infinite loop as big\n // requests are increasing the queue length when moved at the end of the queue.\n uint256 queueLength = withdrawalQueue.length;\n\n // Iterate over requests to be processed\n while (nextRequestId < queueLength) {\n // Stop processing requests if there is not enough gas left to continue the\n // loop and properly end the function call. This prevents an attacker from\n // blocking the withdrawal processing by creating a ton of tiny requests so\n // this function call cannot fit anymore in block gas limit.\n if (gasleft() < 45000) break;\n\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[nextRequestId];\n\n // Skip empty request (processed big requests or cancelled requests)\n if (request.account == address(0)) {}\n //\n // If account has been blacklisted since request emission\n else if (isBlacklisted(request.account)) {\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request in the frozen requests list\n frozenRequests.push(request);\n }\n //\n // Or if request is a big request, move it at the end of the queue for now.\n // This request will be processed manually later using processBigQueuedRequest()\n else if (request.amount > getExpectedRetained() / 2) {\n // Inform listeners of this queued request being moved at the end of the queue\n emit ActivityEvent(\n int256(nextRequestId),\n _msgSender(),\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Moved,\n int256(withdrawalQueue.length)\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Append request at the end of the queue\n withdrawalQueue.push(request);\n }\n //\n // Else, continue request processing\n else {\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Break if the contract doesn't hold enough funds to cover the request\n if (withdrawnAmount > usableUnderlyings - cumulatedWithdrawnAmount) break;\n\n // Accumulate fees and withdrawn amount\n cumulatedFees += fees;\n cumulatedWithdrawnAmount += withdrawnAmount;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(nextRequestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[nextRequestId];\n\n // Transfer underlying tokens to account. Burning L-Tokens is not required\n // as equestWithdrawal() already did it.\n // Security note: Re-entrancy warning are disabled as the request has\n // just been deleted from the queue, it will so be skipped if trying to\n // process it again.\n // slither-disable-next-line reentrancy-no-eth\n underlying().safeTransfer(request.account, withdrawnAmount);\n }\n\n // Increment next request ID\n nextRequestId++;\n }\n\n // Increase unclaimed fees by the amount of cumulated fees\n unclaimedFees += cumulatedFees;\n\n // Decrease usable underlyings by the cumulated amount of withdrawn underlyings\n usableUnderlyings -= cumulatedWithdrawnAmount;\n\n // Decrease total amount queued by the cumulated amount requested\n totalQueued -= cumulatedWithdrawnAmount + cumulatedFees;\n\n // Update new queue cursor\n withdrawalQueueCursor = nextRequestId;\n\n // Retention rate cannot exceeds as the withdrawal decreases both usable\n // underlyings and expected retained amounts by the same number and as the\n // expected retained amount is a subset of usable underlyings amount.\n }\n\n /**\n * @notice Processes a given queued big withdrawal request (one that exceeds half of\n * the retention rate).\n * @dev In contrast to non-big requests processing, this function will uses to fund\n * wallet's balance to fill the request. This allows processing requests that are\n * greater than retention rate without having to exceed this rate on the contract.\n * @param requestId The ID of the big request to process.\n */\n function processBigQueuedRequest(uint256 requestId) external onlyFund whenNotPaused {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure the request is active\n require(request.account != address(0), \"L66\");\n\n // Ensure the request emitter has not been blacklisted since request emission\n require(!isBlacklisted(request.account), \"L50\");\n\n // Ensure this is indeed a big request\n require(request.amount > getExpectedRetained() / 2, \"L51\");\n\n // Retrieve withdrawal fees and net withdrawn amount\n (uint256 withdrawnAmount, uint256 fees) = getWithdrawnAmountAndFees(\n request.account,\n request.amount\n );\n\n // Ensure withdrawn amount can be covered by contract + fund wallet balances\n uint256 fundBalance = underlying().balanceOf(fund);\n require(withdrawnAmount <= usableUnderlyings + fundBalance, \"L52\");\n\n // Increase amount of unclaimed fees accordingly\n unclaimedFees += fees;\n\n // Decrease total queued amount by request amount\n totalQueued -= request.amount;\n\n // Increment queue cursor if request was the next request to be processed\n if (requestId == withdrawalQueueCursor) withdrawalQueueCursor++;\n\n // Inform listeners of this queued withdrawal processing activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n withdrawnAmount,\n Status.Success,\n NO_ID\n );\n\n // Remove request from queue\n delete withdrawalQueue[requestId];\n\n // If fund wallet's balance can cover request, rely on it only\n if (withdrawnAmount <= fundBalance) {\n underlying().safeTransferFrom(_msgSender(), request.account, withdrawnAmount);\n }\n // Else, cover request from both fund wallet and contract balances\n else {\n // Compute amount missing from fund wallet to cover request\n uint256 missingAmount = withdrawnAmount - fundBalance;\n\n // Decrease usable amount of underlying tokens accordingly\n usableUnderlyings -= missingAmount;\n\n // Transfer entire fund balance to request's emitter\n underlying().safeTransferFrom(_msgSender(), request.account, fundBalance);\n\n // Transfer missing amount from contract balance to request emitter\n underlying().safeTransfer(request.account, missingAmount);\n }\n\n // Transfer exceeding underlying tokens to the fund wallet\n _transferExceedingToFund();\n }\n\n /**\n * @notice Cancels a given withdrawal request. The request emitter receive back its\n * L-Tokens and no fees will be charged.\n * @param requestId The ID of the withdrawal request to cancel.\n */\n function cancelWithdrawalRequest(\n uint256 requestId\n ) public whenNotPaused notBlacklisted(_msgSender()) {\n // Retrieve request data\n WithdrawalRequest memory request = withdrawalQueue[requestId];\n\n // Ensure request belongs to caller\n require(_msgSender() == request.account, \"L57\");\n\n // Decrease total amount queued accordingly\n totalQueued -= request.amount;\n\n // Delete the withdrawal request from queue\n delete withdrawalQueue[requestId];\n\n // Inform listeners of this cancelled withdrawal request activity event\n emit ActivityEvent(\n int256(requestId),\n request.account,\n Action.Withdraw,\n request.amount,\n request.amount,\n Status.Cancelled,\n NO_ID\n );\n\n // Mint back L-Tokens to account\n _mint(request.account, uint256(request.amount));\n }\n\n /**\n * @notice Used by the fund wallet to repatriate underlying tokens on the contract\n * whenever those are required to fulfill some withdrawal requests.\n * @dev The function will revert if repatriated amount makes the contract exceeding\n * the retention rate.\n * @param amount The amount of underlying tokens to repatriate.\n */\n function repatriate(uint256 amount) external onlyFund whenNotPaused {\n // Ensure the fund wallet has enough funds to repatriate\n require(amount <= underlying().balanceOf(fund), \"L58\");\n\n // Calculate new contract usable balance\n uint256 newBalance = usableUnderlyings + amount;\n\n // Ensure the new balance doesn't exceed the retention rate\n require(newBalance <= getExpectedRetained(), \"L59\");\n\n // Increase usable underlyings amount by repatriated amount\n usableUnderlyings += amount;\n\n // Transfer amount from fund wallet to contract\n underlying().safeTransferFrom(_msgSender(), address(this), amount);\n }\n\n /// @notice Used by owner to claim fees generated from successful withdrawals.\n function claimFees() external onlyOwner {\n // Ensure there are some fees to claim\n require(unclaimedFees > 0, \"L60\");\n\n // Ensure the contract holds enough underlying tokens to cover fees\n require(usableUnderlyings >= unclaimedFees, \"L61\");\n\n // Decrease usable underlyings amount accordingly\n usableUnderlyings -= unclaimedFees;\n\n // Store fees amount in memory and reset unclaimed fees amount\n uint256 fees = unclaimedFees;\n unclaimedFees = 0;\n\n // Transfer unclaimed fees to owner\n underlying().safeTransfer(owner(), fees);\n }\n}\n" + }, + "contracts/src/PreMining.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {LToken} from \"./LToken.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {Pausable} from \"@openzeppelin/contracts/security/Pausable.sol\";\n\n/**\n * @title PreMining\n * @author Lila Rest (https://lila.rest)\n * @custom:security-contact security@ledgity.com\n\n * @notice PreMining pool contract, allowing accounts to lock underlying tokens in a \n * pre-defined L-Token contract, over a given duration (in months), in exchange of \n * vested LDY rewards.\n * \n * @dev Intuition\n * \n * Lifecycle of a lockdrop pool is composed by 3 main phases:\n * 1) Deposit: During this phase, users can lock their underlying tokens.\n * 2) Claim: During this phase, users can claim their LDY rewards.\n * 3) Recovery: During this phase, owner can recover remaining ERC20 on the contract.\n * \n * Transitioning between two phases is manually triggered by contract's owner.\n * To ensure fair usage of this power and prevent potential misuse:\n * - the Recovery phase cannot start before 3 months after the end of rewards vesting,\n * - the Recovery phase cannot start before 3 months after the maximum lock end.\n * \n * Finally, note that this contract proxies main L-Token contract's functions:\n * - lock() --> deposit()\n * - instantUnlock() --> instantWithdrawal()\n * - requestUnlock() --> requestWithdrawal()\n * This design enables users to interact with the PreMining contract in a similar fashion\n * to the L-Token contract.\n * \n * @dev Definitions:\n * - Locker: An account that has locked underlying tokens in the pool.\n * \n * @custom:security-contact security@ledgity.com\n */\ncontract PreMining is Ownable2Step, Pausable {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Represents the lock information of an account.\n * @param amount Amount of underlying tokens locked.\n * @param duration Duration of the lock (in months).\n * @param hasUnlocked Whether the account has unlocked its locked tokens.\n * @param claimedRewards Amount of LDY rewards already claimed.\n * @param lockEndTimestamp Timestamp at which the account's lock ends.\n */\n struct AccountLock {\n uint240 amount;\n uint8 duration;\n bool hasUnlocked;\n uint216 claimedRewards;\n uint40 lockEndTimestamp;\n }\n\n /// @notice Holds the amount of LDY to be distributed to lockers.\n uint256 public immutable maxDistributedLDY;\n\n /// @notice Holds the maximum total amount of L-Tokens that can be locked.\n uint256 public immutable lockedHardCap;\n\n /// @notice Holds the minimum possible lock duration (in months).\n uint8 public immutable minLockDuration;\n\n /// @notice Holds the maximum possible lock duration (in months).\n uint8 public immutable maxLockDuration;\n\n /// @notice Holds the duration of LDY rewards vesting (in months).\n uint8 public immutable vestingDuration;\n\n /// @notice Holds a reference to the locked L-Token contract.\n LToken public immutable lToken;\n\n /// @notice Holds a reference to the L-Token underlying stablecoin.\n IERC20 public immutable underlyingToken;\n\n /// @notice Holds the max pool weight.\n uint256 public immutable maxWeight;\n\n /// @notice Holds a reference to the LDY token contract.\n IERC20 public ldyToken;\n\n /// @notice Holds lockers' participations informations.\n mapping(address => AccountLock) public accountsLocks;\n\n /// @notice Holds the total amount of locked underlying tokens.\n uint256 public totalLocked;\n\n /// @notice Holds whether the Deposit phase has ended.\n bool public hasDepositPhaseEnded;\n\n /// @notice Holds whether the Claim phase has started.\n bool public hasClaimPhaseStarted;\n\n /// @notice Holds whether the Recovery phase has started.\n bool public hasRecoveryPhaseStarted;\n\n /// @notice Holds the timestamp at which the Claim phase started.\n uint256 public claimPhaseStartTimestamp;\n\n /// @notice Holds an ordered queue of accounts that requested to unlock their tokens.\n address[] public unlockRequests;\n\n /// @notice Holds the index of the first request in the queue (a.k.a, next one to be processed).\n uint256 public unlockRequestsCursor;\n\n /// @notice Emitted to inform about a new lock/deposit.\n event Lock(address indexed account, uint256 amount, uint8 duration);\n\n /// @notice Top-level checks and code shared by both unlock functions.\n modifier safeUnlock() {\n // Ensure that the account's lock has ended\n require(accountsLocks[msg.sender].lockEndTimestamp <= block.timestamp, \"L68\");\n\n // Ensure the account hasn't already unlocked its tokens\n require(!accountsLocks[msg.sender].hasUnlocked, \"L69\");\n\n // Ensure the account has something to unlock\n require(accountsLocks[msg.sender].amount > 0, \"L70\");\n\n // Indicate that account has unlocked its tokens\n accountsLocks[msg.sender].hasUnlocked = true;\n _;\n }\n\n /**\n * @notice This constructor function etches the lockdrop terms in immutable states.\n * Ensuring that those terms cannot be modified after deployment.\n * @param lTokenAddress_ Address of the L-Token contract to use.\n * @param maxDistributedLDY_ Amount of LDY to be distributed to lockers.\n * @param lockedHardCap_ Maximum total amount of L-Tokens that can be locked.\n * @param minLockDuration_ Minimum possible lock duration (in months).\n * @param maxLockDuration_ Maximum possible lock duration (in months).\n * @param vestingDuration_ Duration of LDY rewards vesting (in months).\n */\n constructor(\n address lTokenAddress_,\n uint256 maxDistributedLDY_,\n uint256 lockedHardCap_,\n uint8 minLockDuration_,\n uint8 maxLockDuration_,\n uint8 vestingDuration_\n ) {\n // Ensure minLockDuration is at least 1 month\n require(minLockDuration_ >= 1, \"L72\");\n\n // Ensure minLockDuration is not greater than maxLockDuration\n require(minLockDuration_ <= maxLockDuration_, \"L73\");\n\n // Set immutable states\n lToken = LToken(lTokenAddress_);\n underlyingToken = IERC20(address(lToken.underlying()));\n lockedHardCap = lockedHardCap_;\n maxDistributedLDY = maxDistributedLDY_;\n minLockDuration = minLockDuration_;\n maxLockDuration = maxLockDuration_;\n vestingDuration = vestingDuration_;\n maxWeight = lockedHardCap * uint256(maxLockDuration);\n }\n\n /**\n * @notice Public implementation of Pausable's pausing and unpausing functions, but\n * restricted to contract's owner.\n */\n function pause() public onlyOwner {\n _pause();\n }\n\n function unpause() public onlyOwner {\n _unpause();\n }\n\n /**\n * @notice Updates the LDY token contract address.\n * @dev As the first Ledgity Yield lockdrop campaigns will start before the LDY TGE,\n * this function allows the contract's owner to set the LDY token address once it\n * becomes available.\n * @param ldyTokenAddress Address of the LDY token contract.\n */\n function setLDYToken(address ldyTokenAddress) external onlyOwner {\n // Prevent owner from changing the LDY address after Claim phase has started\n require(!hasClaimPhaseStarted, \"L74\");\n\n // Set LDY token address\n ldyToken = IERC20(ldyTokenAddress);\n }\n\n /**\n * @notice Closes the Deposit phase. After calling this function, account won't be\n * able to lock additional underlying tokens anymore.\n */\n function endDepositPhase() external onlyOwner {\n hasDepositPhaseEnded = true;\n }\n\n /**\n * @notice Opens the Claim phase. After calling this function, lockers will be able\n * to start claiming their LDY rewards.\n */\n function startClaimPhase() external onlyOwner {\n // Ensure Claim phase has not already started\n require(!hasClaimPhaseStarted, \"L76\");\n\n // Ensure that LDY token address is available\n require(address(ldyToken) != address(0), \"L77\");\n\n // Set Claim phase as started and store the start timestamp\n hasClaimPhaseStarted = true;\n claimPhaseStartTimestamp = block.timestamp;\n }\n\n /**\n * @notice Opens the Recovery phase. After calling this function, the contract owner\n * will be able to recover remaining ERC20 tokens on the contract.\n * Note that this won't close the Claim phase and lockers will still be able to claim\n * their LDY rewards.\n */\n function startRecoveryPhase() external onlyOwner {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L79\");\n\n // Compute some durations in seconds\n uint256 threeMonthsInSecond = 3 * 30 days;\n uint256 vestingInSecond = uint256(vestingDuration) * 30 days;\n uint256 maxLockInSecond = uint256(maxLockDuration) * 30 days;\n\n // Compute timestamp of vesting end + 3 months\n uint256 afterVestingTimestamp = claimPhaseStartTimestamp +\n vestingInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the end of reward vesting\n // This prevents owner from recovering LDY before lockers can claim their rewards\n require(block.timestamp >= afterVestingTimestamp, \"L80\");\n\n // Compute end of maximum lock + 3 months\n // Note that claimPhaseStartTimestamp is used for simplicity even if it can exist a time\n // span between Deposit and Claim phases.\n uint256 afterMaxLockTimestamp = claimPhaseStartTimestamp +\n maxLockInSecond +\n threeMonthsInSecond;\n\n // Ensure we are at least 3 months after the maximum lock end\n // This prevents owner from recovering underlying tokens before lockers can unlock those\n require(block.timestamp >= afterMaxLockTimestamp, \"L81\");\n\n // Set recovery phase as started\n hasRecoveryPhaseStarted = true;\n }\n\n /**\n * @notice Recovers a specified amount of a given token address. Will revert if\n * recovery phase has not started yet or if the contract doesn't hold enough tokens.\n * @param tokenAddress The address of the token to recover.\n * @param amount The amount of token to recover.\n */\n function recoverERC20(address tokenAddress, uint256 amount) external onlyOwner {\n // Ensure recovery phase has started\n require(hasRecoveryPhaseStarted, \"L82\");\n\n // Create a reference to token's contract\n IERC20 tokenContract = IERC20(tokenAddress);\n\n // Ensure there is enough tokens to recover\n require(tokenContract.balanceOf(address(this)) >= amount, \"L83\");\n\n // Transfer the recovered token amount to the sender (owner)\n tokenContract.safeTransfer(msg.sender, amount);\n }\n\n /**\n * @notice Compute the total amount of LDY rewards that a given account is eligible to.\n * @dev Note: This function neither considers vesting nor already claimed rewards.\n * @param account The account to compute the eligible rewards of.\n * @return The total amount of LDY rewards that the account is eligible to.\n */\n function eligibleRewardsOf(address account) public view returns (uint256) {\n // Compute account's lock weight\n uint256 lockerWeight = accountsLocks[account].amount * accountsLocks[account].duration;\n\n // Compute amount of LDY that this locker is eligible to\n if (maxWeight == 0) return 0;\n else return (maxDistributedLDY * lockerWeight) / maxWeight;\n }\n\n /**\n * @notice Allows locking a specified amount of underlying tokens for a given duration.\n * By locking, an account became eligible to a portion of the distributed LDY rewards.\n * @dev This function proxies LToken.deposit()\n * @dev Lockers can extend their lock duration by calling this function again with a\n * greater duration and 0 as amount.\n * @param amount Amount of underlying tokens to lock.\n * @param duration Duration of the lock (in months).\n */\n function lock(uint256 amount, uint8 duration) external whenNotPaused {\n // Ensure Deposit phase has not ended yet\n require(!hasDepositPhaseEnded, \"L84\");\n\n // Ensure account hasn't already unlocked a past lock\n require(!accountsLocks[msg.sender].hasUnlocked, \"L71\");\n\n // Ensure lock duration is in valid range\n require(duration >= minLockDuration && duration <= maxLockDuration, \"L85\");\n\n // Ensure it won't exceed the hardcap\n require(totalLocked + amount <= uint256(lockedHardCap), \"L86\");\n\n // Increase account's locked amount\n accountsLocks[msg.sender].amount += uint240(amount);\n\n // Increase total locked amount accordingly\n totalLocked += amount;\n\n // Use existing lock duration if greater than the new one\n uint8 existingDuration = accountsLocks[msg.sender].duration;\n uint8 appliedDuration = existingDuration > duration ? existingDuration : duration;\n\n // Update account's lock duration\n accountsLocks[msg.sender].duration = appliedDuration;\n\n // Update account's lock end timestamp\n accountsLocks[msg.sender].lockEndTimestamp = uint40(\n block.timestamp + uint40(appliedDuration) * 30 days\n );\n\n // Emit a Lock event\n emit Lock(msg.sender, amount, appliedDuration);\n\n // If amount is 0, skip deposit\n if (amount == 0) return;\n\n // Transfer underlyingToken from account to contract\n underlyingToken.safeTransferFrom(msg.sender, address(this), amount);\n\n // Deposit USDC in the L-Token contract\n underlyingToken.safeApprove(address(lToken), amount);\n lToken.deposit(amount);\n }\n\n /**\n * @notice Allows the caller to instaneously unlock its locked amount of underlying\n * tokens.\n * @dev In order to save some gas and time to users, frontends should propose this\n * function to users only when it has been verified that it will not revert. They\n * should propose the requestUnlock() function otherwise.\n */\n function instantUnlock() external whenNotPaused safeUnlock {\n // Retrieve underlying tokens from the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.instantWithdrawal(unlockedAmount);\n\n // Transfer underlying tokens back to caller\n underlyingToken.safeTransfer(msg.sender, unlockedAmount);\n }\n\n /**\n * @notice Allows the call to request for the unlocking of its locked amount of\n * underlying tokens. The request will be automatically processed later.\n * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees\n * paid by the withdrawer wallet.\n */\n function requestUnlock() external payable whenNotPaused safeUnlock {\n // Put account in the unlock requests queue\n unlockRequests.push(msg.sender);\n\n // Request underlying tokens to the L-Token contract\n uint256 unlockedAmount = accountsLocks[msg.sender].amount;\n lToken.requestWithdrawal{value: msg.value}(unlockedAmount);\n }\n\n /**\n * @notice Processes queued unlock requests until there is else no more requests,\n * else not enough underlying tokens to continue.\n */\n function processUnlockRequests() external onlyOwner {\n // Store the current request ID to process\n uint256 processedId = unlockRequestsCursor;\n\n // Loop over remaining requests\n while (processedId < unlockRequests.length) {\n // Prevent OOG by stopping request processing if there is not enough gas left\n // to continue the loop and properly end the function call.\n if (gasleft() < 45000) break;\n\n // Retrieve the request account\n address unlockAccount = unlockRequests[processedId];\n\n // Retrieve the unlocked amount\n uint256 unlockAmount = accountsLocks[unlockAccount].amount;\n\n // If the request has already been processed, skip it\n if (unlockAccount != address(0)) {\n // If the contract doesn't hold enough underlying tokens to process the request, stop here\n if (underlyingToken.balanceOf(address(this)) < unlockAmount) break;\n\n // Delete the request\n delete unlockRequests[processedId];\n\n // Transfer underlying back to account\n underlyingToken.safeTransfer(unlockAccount, unlockAmount);\n }\n\n // Increment processed request ID\n processedId++;\n }\n\n // Write back the cursor in storage\n unlockRequestsCursor = processedId;\n }\n\n /**\n * @notice Computes the amount of LDY rewards available to claim for a given account.\n * @dev This function considers vesting and already claimed rewards.\n * @param account The account to compute the available rewards of.\n * @return The amount of LDY rewards available to claim.\n */\n function availableToClaim(address account) public view returns (uint256) {\n // Compute total amount of rewards allocated to this locker\n uint256 totalEligibleRewards = eligibleRewardsOf(account);\n\n // Compute vesting duration in seconds\n uint256 vestingInSeconds = uint256(vestingDuration) * 30 days;\n\n // Compute elapsed months since claim phase started, and cap it to vesting duration\n uint256 elapsedTime = block.timestamp - claimPhaseStartTimestamp;\n if (elapsedTime > vestingInSeconds) elapsedTime = vestingInSeconds;\n\n // Compute total available to claim (proportionally to elapsed time)\n uint256 totalAvailableToClaim = (totalEligibleRewards * elapsedTime) / vestingInSeconds;\n\n // Else return net claimable (available minus already claimed)\n return totalAvailableToClaim - accountsLocks[account].claimedRewards;\n }\n\n /// @notice Allows the caller to claim its available LDY rewards.\n function claimRewards() external whenNotPaused {\n // Ensure Claim phase has started\n require(hasClaimPhaseStarted, \"L87\");\n\n // Compute claimable LDY rewards\n uint256 claimableLDY = availableToClaim(msg.sender);\n\n // Increase account claimed amount accordingly\n accountsLocks[msg.sender].claimedRewards += uint216(claimableLDY);\n\n // Transfer rewards to account\n ldyToken.safeTransfer(msg.sender, claimableLDY);\n }\n}\n" + } + }, + "settings": { + "evmVersion": "london", + "optimizer": { + "enabled": true, + "runs": 100 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/contracts/src/LToken.sol b/contracts/src/LToken.sol index d219a885..cb5e8154 100644 --- a/contracts/src/LToken.sol +++ b/contracts/src/LToken.sol @@ -137,6 +137,11 @@ contract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradea */ ITransfersListener[] public transfersListeners; + /** + * @notice Holds the withdrwalFee amount in ETH that will be sent to withdrawer wallet. + */ + uint256 public withdrwalFeeInEth; + /** * @notice Emitted to inform listeners about a change in the contract's TVL. * @dev TVL = realTotalSupply() @@ -230,6 +235,9 @@ contract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradea // any loss of funds if a deposit/withdrawal is made before those are manually set. withdrawer = payable(owner()); fund = payable(owner()); + + // Set initial withdrwalFeeInEth + withdrwalFeeInEth = 0.00075 * 1e18; } /** @@ -274,6 +282,15 @@ contract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradea feesRateUD7x3 = feesRateUD7x3_; } + /** + * @notice Updates the current withdrawalFeeInETH. + * @param withdrwalFeeInEth_ The new withdrawalFee in ETH. + */ + function setWithdrwalFeeInEth(uint256 withdrwalFeeInEth_) public onlyOwner { + require(withdrwalFeeInEth <= MAX_FEES_RATE_UD7x3, "L88"); + withdrwalFeeInEth = withdrwalFeeInEth_; + } + /** * @notice Updates the current underlying token retention rate. * @dev The retention rate is capped at 10%, which ensures that no more than 10% of @@ -672,7 +689,7 @@ contract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradea /** * @notice Allows requesting the exchange of a given amount of L-Tokens for the same * amount of underlying tokens. The request will be automatically processed later. - * @dev The sender must attach 0.003 ETH to pre-pay the future processing gas fees + * @dev The sender must attach withdrwalFeeInETH to pre-pay the future processing gas fees * paid by the withdrawer wallet. * @param amount The amount L-Tokens to withdraw. */ @@ -686,7 +703,7 @@ contract LToken is ERC20BaseUpgradeable, InvestUpgradeable, ERC20WrapperUpgradea require(amount <= type(uint96).max, "L54"); // Ensure the sender attached the pre-paid processing gas fees - require(msg.value == 0.003 * 10 ** 18, "L55"); + require(msg.value == withdrwalFeeInEth, "L55"); // Create withdrawal request data WithdrawalRequest memory request = WithdrawalRequest({ diff --git a/hardhat.config.cts b/hardhat.config.cts index 3818e157..b727dc72 100644 --- a/hardhat.config.cts +++ b/hardhat.config.cts @@ -76,7 +76,7 @@ const config: HardhatUserConfig = { evmVersion: "london", optimizer: { enabled: true, - runs: 200, + runs: 100, }, }, }, @@ -150,6 +150,7 @@ const config: HardhatUserConfig = { chainId: 42161, url: "https://arbitrum-mainnet.infura.io/v3/05368c74554249babb6f126ccf325401", accounts: deployerPrivateKey ? [deployerPrivateKey] : [], + deploy: ["./contracts/hardhat/arbi-mainnet-deploy"], saveDeployments: true, verify: { etherscan: { diff --git a/package.json b/package.json index 60092464..08bbbb04 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ "graph:prepare-okx-mainnet": "cd subgraph && mustache ./config/okx-mainnet.json ./subgraph.template.yaml > ./subgraph.yaml", "graph:deploy-okx-mainnet": "cd subgraph && graph deploy --node https://api.studio.thegraph.com/deploy/ ledgity-okxmain ./subgraph.yaml", "graph:prepare-eth-mainnet": "cd subgraph && mustache ./config/ethereum-mainnet.json ./subgraph.template.yaml > ./subgraph.yaml", - "graph:deploy-eth-mainnet": "cd subgraph && graph deploy --node https://api.studio.thegraph.com/deploy/ ledgity-eth-mainnet ./subgraph.yaml" + "graph:deploy-eth-mainnet": "cd subgraph && graph deploy --node https://api.studio.thegraph.com/deploy/ ledgity-eth-mainnet ./subgraph.yaml", + "graph:prepare-arbi-mainnet": "cd subgraph && mustache ./config/arbitrum-mainnet.json ./subgraph.template.yaml > ./subgraph.yaml", + "graph:deploy-arbi-mainnet": "cd subgraph && graph deploy --node https://api.studio.thegraph.com/deploy/ ledgity-arbi-main ./subgraph.yaml" }, "dependencies": { "@auth/prisma-adapter": "^1.0.11", diff --git a/src/config/chains/index.ts b/src/config/chains/index.ts index e23fb02f..a65d3bac 100644 --- a/src/config/chains/index.ts +++ b/src/config/chains/index.ts @@ -33,4 +33,6 @@ export const SUBGRAPH_CLIENT_URLS = { [ChainId.XLAYER]: "https://api.studio.thegraph.com/query/60646/ledgity-okxmain/version/latest", [ChainId.ETHEREUM]: "https://api.studio.thegraph.com/query/60646/ledgity-eth-mainnet/version/latest", + [ChainId.ARBITRUM_ONE]: + "https://api.studio.thegraph.com/query/60646/ledgity-arbi-main/version/latest", } satisfies Record; diff --git a/src/generated.ts b/src/generated.ts index 7e69c25e..319c7274 100644 --- a/src/generated.ts +++ b/src/generated.ts @@ -1106,7 +1106,7 @@ export const ldyConfig = { address: ldyAddress, abi: ldyAbi } as const * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -1696,7 +1696,7 @@ export const ldyStakingAbi = [ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -1708,7 +1708,7 @@ export const ldyStakingAddress = { 195: '0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895', 196: '0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895', 31337: '0xa513E6E4b8f2a923D98304ec87F64353C4D5C853', - 42161: '0x4e80beDBD58b084a8946b7BA6814c28906Be2d02', + 42161: '0x98002b5c06b44c8769dA3DAe97CA498aB6F97137', 59140: '0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6', 59144: '0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1', 84532: '0xA798B51F15B0024880f835723C681cB730835628', @@ -1720,7 +1720,7 @@ export const ldyStakingAddress = { * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -2339,6 +2339,15 @@ export const lTokenAbi = [ name: 'setWithdrawer', outputs: [], }, + { + stateMutability: 'nonpayable', + type: 'function', + inputs: [ + { name: 'withdrwalFeeInEth_', internalType: 'uint256', type: 'uint256' }, + ], + name: 'setWithdrwalFeeInEth', + outputs: [], + }, { stateMutability: 'nonpayable', type: 'function', @@ -2513,6 +2522,13 @@ export const lTokenAbi = [ name: 'withdrawer', outputs: [{ name: '', internalType: 'address payable', type: 'address' }], }, + { + stateMutability: 'view', + type: 'function', + inputs: [], + name: 'withdrwalFeeInEth', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + }, ] as const ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5316,7 +5332,7 @@ export const useWatchLdyTransferEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5334,7 +5350,7 @@ export const useReadLdyStaking = /*#__PURE__*/ createUseReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5354,7 +5370,7 @@ export const useReadLdyStakingMultiplierBasis = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5373,7 +5389,7 @@ export const useReadLdyStakingEarned = /*#__PURE__*/ createUseReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5392,7 +5408,7 @@ export const useReadLdyStakingFinishAt = /*#__PURE__*/ createUseReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5412,7 +5428,7 @@ export const useReadLdyStakingGetEarnedUser = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5432,7 +5448,7 @@ export const useReadLdyStakingGetStakeDurationInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5452,7 +5468,7 @@ export const useReadLdyStakingGetUserStakes = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5472,7 +5488,7 @@ export const useReadLdyStakingGlobalBlacklist = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5493,7 +5509,7 @@ export const useReadLdyStakingGlobalOwner = /*#__PURE__*/ createUseReadContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5514,7 +5530,7 @@ export const useReadLdyStakingGlobalPause = /*#__PURE__*/ createUseReadContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5534,7 +5550,7 @@ export const useReadLdyStakingHighTierAccounts = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5554,7 +5570,7 @@ export const useReadLdyStakingLastTimeRewardApplicable = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5574,7 +5590,7 @@ export const useReadLdyStakingLastUpdateTime = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5593,7 +5609,7 @@ export const useReadLdyStakingOwner = /*#__PURE__*/ createUseReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5612,7 +5628,7 @@ export const useReadLdyStakingPaused = /*#__PURE__*/ createUseReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5632,7 +5648,7 @@ export const useReadLdyStakingProxiableUuid = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5652,7 +5668,7 @@ export const useReadLdyStakingRenounceOwnership = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5672,7 +5688,7 @@ export const useReadLdyStakingRewardPerToken = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5692,7 +5708,7 @@ export const useReadLdyStakingRewardPerTokenStored = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5712,7 +5728,7 @@ export const useReadLdyStakingRewardRatePerSec = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5732,7 +5748,7 @@ export const useReadLdyStakingRewardsDuration = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5752,7 +5768,7 @@ export const useReadLdyStakingStakeAmountForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5772,7 +5788,7 @@ export const useReadLdyStakingStakeDurationForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5792,7 +5808,7 @@ export const useReadLdyStakingStakeDurationInfos = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5812,7 +5828,7 @@ export const useReadLdyStakingStakeRewardToken = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5831,7 +5847,7 @@ export const useReadLdyStakingTierOf = /*#__PURE__*/ createUseReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5851,7 +5867,7 @@ export const useReadLdyStakingTotalRewards = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5872,7 +5888,7 @@ export const useReadLdyStakingTotalStaked = /*#__PURE__*/ createUseReadContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5892,7 +5908,7 @@ export const useReadLdyStakingTotalWeightedStake = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5912,7 +5928,7 @@ export const useReadLdyStakingTransferOwnership = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5932,7 +5948,7 @@ export const useReadLdyStakingUserStakingInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5950,7 +5966,7 @@ export const useWriteLdyStaking = /*#__PURE__*/ createUseWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5967,7 +5983,7 @@ export const useWriteLdyStakingGetReward = /*#__PURE__*/ createUseWriteContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -5987,7 +6003,7 @@ export const useWriteLdyStakingInitialize = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6007,7 +6023,7 @@ export const useWriteLdyStakingNotifyRewardAmount = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6027,7 +6043,7 @@ export const useWriteLdyStakingPushStakeDurationInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6047,7 +6063,7 @@ export const useWriteLdyStakingRecoverErc20 = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6067,7 +6083,7 @@ export const useWriteLdyStakingSetRewardsDuration = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6087,7 +6103,7 @@ export const useWriteLdyStakingSetStakeAmountForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6107,7 +6123,7 @@ export const useWriteLdyStakingSetStakeDurationForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6126,7 +6142,7 @@ export const useWriteLdyStakingStake = /*#__PURE__*/ createUseWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6145,7 +6161,7 @@ export const useWriteLdyStakingUnstake = /*#__PURE__*/ createUseWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6162,7 +6178,7 @@ export const useWriteLdyStakingUpgradeTo = /*#__PURE__*/ createUseWriteContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6182,7 +6198,7 @@ export const useWriteLdyStakingUpgradeToAndCall = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6200,7 +6216,7 @@ export const useSimulateLdyStaking = /*#__PURE__*/ createUseSimulateContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6220,7 +6236,7 @@ export const useSimulateLdyStakingGetReward = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6240,7 +6256,7 @@ export const useSimulateLdyStakingInitialize = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6260,7 +6276,7 @@ export const useSimulateLdyStakingNotifyRewardAmount = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6280,7 +6296,7 @@ export const useSimulateLdyStakingPushStakeDurationInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6300,7 +6316,7 @@ export const useSimulateLdyStakingRecoverErc20 = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6320,7 +6336,7 @@ export const useSimulateLdyStakingSetRewardsDuration = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6340,7 +6356,7 @@ export const useSimulateLdyStakingSetStakeAmountForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6360,7 +6376,7 @@ export const useSimulateLdyStakingSetStakeDurationForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6380,7 +6396,7 @@ export const useSimulateLdyStakingStake = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6400,7 +6416,7 @@ export const useSimulateLdyStakingUnstake = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6420,7 +6436,7 @@ export const useSimulateLdyStakingUpgradeTo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6440,7 +6456,7 @@ export const useSimulateLdyStakingUpgradeToAndCall = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6459,7 +6475,7 @@ export const useWatchLdyStakingEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6479,7 +6495,7 @@ export const useWatchLdyStakingAdminChangedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6499,7 +6515,7 @@ export const useWatchLdyStakingBeaconUpgradedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6519,7 +6535,7 @@ export const useWatchLdyStakingInitializedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6539,7 +6555,7 @@ export const useWatchLdyStakingNotifiedRewardAmountEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6559,7 +6575,7 @@ export const useWatchLdyStakingOwnershipTransferredEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6579,7 +6595,7 @@ export const useWatchLdyStakingPausedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6599,7 +6615,7 @@ export const useWatchLdyStakingRewardPaidEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6619,7 +6635,7 @@ export const useWatchLdyStakingStakedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6639,7 +6655,7 @@ export const useWatchLdyStakingUnpausedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6659,7 +6675,7 @@ export const useWatchLdyStakingUnstakedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -6992,6 +7008,15 @@ export const useReadLTokenWithdrawer = /*#__PURE__*/ createUseReadContract({ functionName: 'withdrawer', }) +/** + * Wraps __{@link useReadContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"withdrwalFeeInEth"` + */ +export const useReadLTokenWithdrwalFeeInEth = + /*#__PURE__*/ createUseReadContract({ + abi: lTokenAbi, + functionName: 'withdrwalFeeInEth', + }) + /** * Wraps __{@link useWriteContract}__ with `abi` set to __{@link lTokenAbi}__ */ @@ -7175,6 +7200,15 @@ export const useWriteLTokenSetWithdrawer = /*#__PURE__*/ createUseWriteContract( { abi: lTokenAbi, functionName: 'setWithdrawer' }, ) +/** + * Wraps __{@link useWriteContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"setWithdrwalFeeInEth"` + */ +export const useWriteLTokenSetWithdrwalFeeInEth = + /*#__PURE__*/ createUseWriteContract({ + abi: lTokenAbi, + functionName: 'setWithdrwalFeeInEth', + }) + /** * Wraps __{@link useWriteContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"startRewardsRedirection"` */ @@ -7424,6 +7458,15 @@ export const useSimulateLTokenSetWithdrawer = functionName: 'setWithdrawer', }) +/** + * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"setWithdrwalFeeInEth"` + */ +export const useSimulateLTokenSetWithdrwalFeeInEth = + /*#__PURE__*/ createUseSimulateContract({ + abi: lTokenAbi, + functionName: 'setWithdrwalFeeInEth', + }) + /** * Wraps __{@link useSimulateContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"startRewardsRedirection"` */ @@ -10974,7 +11017,7 @@ export const watchLdyTransferEvent = /*#__PURE__*/ createWatchContractEvent({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -10992,7 +11035,7 @@ export const readLdyStaking = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11011,7 +11054,7 @@ export const readLdyStakingMultiplierBasis = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11030,7 +11073,7 @@ export const readLdyStakingEarned = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11049,7 +11092,7 @@ export const readLdyStakingFinishAt = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11068,7 +11111,7 @@ export const readLdyStakingGetEarnedUser = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11088,7 +11131,7 @@ export const readLdyStakingGetStakeDurationInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11107,7 +11150,7 @@ export const readLdyStakingGetUserStakes = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11126,7 +11169,7 @@ export const readLdyStakingGlobalBlacklist = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11145,7 +11188,7 @@ export const readLdyStakingGlobalOwner = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11164,7 +11207,7 @@ export const readLdyStakingGlobalPause = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11183,7 +11226,7 @@ export const readLdyStakingHighTierAccounts = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11203,7 +11246,7 @@ export const readLdyStakingLastTimeRewardApplicable = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11222,7 +11265,7 @@ export const readLdyStakingLastUpdateTime = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11241,7 +11284,7 @@ export const readLdyStakingOwner = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11260,7 +11303,7 @@ export const readLdyStakingPaused = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11279,7 +11322,7 @@ export const readLdyStakingProxiableUuid = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11300,7 +11343,7 @@ export const readLdyStakingRenounceOwnership = /*#__PURE__*/ createReadContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11319,7 +11362,7 @@ export const readLdyStakingRewardPerToken = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11339,7 +11382,7 @@ export const readLdyStakingRewardPerTokenStored = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11358,7 +11401,7 @@ export const readLdyStakingRewardRatePerSec = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11377,7 +11420,7 @@ export const readLdyStakingRewardsDuration = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11397,7 +11440,7 @@ export const readLdyStakingStakeAmountForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11417,7 +11460,7 @@ export const readLdyStakingStakeDurationForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11437,7 +11480,7 @@ export const readLdyStakingStakeDurationInfos = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11456,7 +11499,7 @@ export const readLdyStakingStakeRewardToken = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11475,7 +11518,7 @@ export const readLdyStakingTierOf = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11494,7 +11537,7 @@ export const readLdyStakingTotalRewards = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11513,7 +11556,7 @@ export const readLdyStakingTotalStaked = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11533,7 +11576,7 @@ export const readLdyStakingTotalWeightedStake = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11554,7 +11597,7 @@ export const readLdyStakingTransferOwnership = /*#__PURE__*/ createReadContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11573,7 +11616,7 @@ export const readLdyStakingUserStakingInfo = /*#__PURE__*/ createReadContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11591,7 +11634,7 @@ export const writeLdyStaking = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11610,7 +11653,7 @@ export const writeLdyStakingGetReward = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11629,7 +11672,7 @@ export const writeLdyStakingInitialize = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11649,7 +11692,7 @@ export const writeLdyStakingNotifyRewardAmount = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11669,7 +11712,7 @@ export const writeLdyStakingPushStakeDurationInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11688,7 +11731,7 @@ export const writeLdyStakingRecoverErc20 = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11708,7 +11751,7 @@ export const writeLdyStakingSetRewardsDuration = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11728,7 +11771,7 @@ export const writeLdyStakingSetStakeAmountForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11748,7 +11791,7 @@ export const writeLdyStakingSetStakeDurationForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11767,7 +11810,7 @@ export const writeLdyStakingStake = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11786,7 +11829,7 @@ export const writeLdyStakingUnstake = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11805,7 +11848,7 @@ export const writeLdyStakingUpgradeTo = /*#__PURE__*/ createWriteContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11825,7 +11868,7 @@ export const writeLdyStakingUpgradeToAndCall = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11843,7 +11886,7 @@ export const simulateLdyStaking = /*#__PURE__*/ createSimulateContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11860,7 +11903,7 @@ export const simulateLdyStakingGetReward = /*#__PURE__*/ createSimulateContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11880,7 +11923,7 @@ export const simulateLdyStakingInitialize = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11900,7 +11943,7 @@ export const simulateLdyStakingNotifyRewardAmount = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11920,7 +11963,7 @@ export const simulateLdyStakingPushStakeDurationInfo = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11940,7 +11983,7 @@ export const simulateLdyStakingRecoverErc20 = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11960,7 +12003,7 @@ export const simulateLdyStakingSetRewardsDuration = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -11980,7 +12023,7 @@ export const simulateLdyStakingSetStakeAmountForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12000,7 +12043,7 @@ export const simulateLdyStakingSetStakeDurationForPerks = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12019,7 +12062,7 @@ export const simulateLdyStakingStake = /*#__PURE__*/ createSimulateContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12038,7 +12081,7 @@ export const simulateLdyStakingUnstake = /*#__PURE__*/ createSimulateContract({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12055,7 +12098,7 @@ export const simulateLdyStakingUpgradeTo = /*#__PURE__*/ createSimulateContract( * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12075,7 +12118,7 @@ export const simulateLdyStakingUpgradeToAndCall = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12093,7 +12136,7 @@ export const watchLdyStakingEvent = /*#__PURE__*/ createWatchContractEvent({ * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12113,7 +12156,7 @@ export const watchLdyStakingAdminChangedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12133,7 +12176,7 @@ export const watchLdyStakingBeaconUpgradedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12153,7 +12196,7 @@ export const watchLdyStakingInitializedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12173,7 +12216,7 @@ export const watchLdyStakingNotifiedRewardAmountEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12193,7 +12236,7 @@ export const watchLdyStakingOwnershipTransferredEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12213,7 +12256,7 @@ export const watchLdyStakingPausedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12233,7 +12276,7 @@ export const watchLdyStakingRewardPaidEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12253,7 +12296,7 @@ export const watchLdyStakingStakedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12273,7 +12316,7 @@ export const watchLdyStakingUnpausedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12293,7 +12336,7 @@ export const watchLdyStakingUnstakedEvent = * - [__View Contract on Ethereum Etherscan__](https://etherscan.io/address/0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e) * - [__View Contract on X1 Testnet Ok Link__](https://www.oklink.com/x1-test/address/0xd132b6D2cfACa8B5b9e0bA8004Df6275380fa895) * - - * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x4e80beDBD58b084a8946b7BA6814c28906Be2d02) + * - [__View Contract on Arbitrum One Arbiscan__](https://arbiscan.io/address/0x98002b5c06b44c8769dA3DAe97CA498aB6F97137) * - [__View Contract on Linea Goerli Testnet Etherscan__](https://goerli.lineascan.build/address/0x7A78A93dad6A64d0A92C913C008dC79dBf919Fa6) * - [__View Contract on Linea Mainnet Etherscan__](https://lineascan.build/address/0x627Ff3485a2e34916a6E1c0D0b350A422F5d89D1) * - [__View Contract on Base Sepolia Basescan__](https://sepolia.basescan.org/address/0xA798B51F15B0024880f835723C681cB730835628) @@ -12618,6 +12661,14 @@ export const readLTokenWithdrawer = /*#__PURE__*/ createReadContract({ functionName: 'withdrawer', }) +/** + * Wraps __{@link readContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"withdrwalFeeInEth"` + */ +export const readLTokenWithdrwalFeeInEth = /*#__PURE__*/ createReadContract({ + abi: lTokenAbi, + functionName: 'withdrwalFeeInEth', +}) + /** * Wraps __{@link writeContract}__ with `abi` set to __{@link lTokenAbi}__ */ @@ -12794,6 +12845,15 @@ export const writeLTokenSetWithdrawer = /*#__PURE__*/ createWriteContract({ functionName: 'setWithdrawer', }) +/** + * Wraps __{@link writeContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"setWithdrwalFeeInEth"` + */ +export const writeLTokenSetWithdrwalFeeInEth = + /*#__PURE__*/ createWriteContract({ + abi: lTokenAbi, + functionName: 'setWithdrwalFeeInEth', + }) + /** * Wraps __{@link writeContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"startRewardsRedirection"` */ @@ -13034,6 +13094,15 @@ export const simulateLTokenSetWithdrawer = /*#__PURE__*/ createSimulateContract( { abi: lTokenAbi, functionName: 'setWithdrawer' }, ) +/** + * Wraps __{@link simulateContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"setWithdrwalFeeInEth"` + */ +export const simulateLTokenSetWithdrwalFeeInEth = + /*#__PURE__*/ createSimulateContract({ + abi: lTokenAbi, + functionName: 'setWithdrwalFeeInEth', + }) + /** * Wraps __{@link simulateContract}__ with `abi` set to __{@link lTokenAbi}__ and `functionName` set to `"startRewardsRedirection"` */ diff --git a/src/lib/dapp/chains.ts b/src/lib/dapp/chains.ts index f2c9f028..20d449b3 100644 --- a/src/lib/dapp/chains.ts +++ b/src/lib/dapp/chains.ts @@ -76,7 +76,7 @@ const devChains: readonly [Chain, ...Chain[]] = [ mainnet, sepolia, hardhat, - arbitrumGoerli, + arbitrum, xlayerTestnet, xlayerMainnet, lineaTestnet, diff --git a/subgraph/build/contracts/abis/LToken.json b/subgraph/build/contracts/abis/LToken.json index c3277242..a21f1597 100644 --- a/subgraph/build/contracts/abis/LToken.json +++ b/subgraph/build/contracts/abis/LToken.json @@ -962,6 +962,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrwalFeeInEth_", + "type": "uint256" + } + ], + "name": "setWithdrwalFeeInEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1297,5 +1310,18 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "withdrwalFeeInEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/subgraph/build/subgraph.yaml b/subgraph/build/subgraph.yaml index c58e4183..5c75df49 100644 --- a/subgraph/build/subgraph.yaml +++ b/subgraph/build/subgraph.yaml @@ -6,11 +6,11 @@ schema: dataSources: - kind: ethereum/contract name: LTokenSignaler - network: mainnet + network: arbitrum-one source: - address: "0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e" + address: "0x011C5B18aBC74A341209b12D1A6fD7B59E423428" abi: LTokenSignaler - startBlock: 20008643 + startBlock: 1756244 mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -28,11 +28,11 @@ dataSources: handler: handleSignaledLToken - kind: ethereum name: LdyStaking - network: mainnet + network: arbitrum-one source: - address: "0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e" + address: "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137" abi: LdyStaking - startBlock: 20008643 + startBlock: 218746026 mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -58,7 +58,7 @@ dataSources: templates: - kind: ethereum/contract name: LToken - network: mainnet + network: arbitrum-one source: abi: LToken mapping: diff --git a/subgraph/config/arbitrum-mainnet.json b/subgraph/config/arbitrum-mainnet.json new file mode 100644 index 00000000..c2912cfd --- /dev/null +++ b/subgraph/config/arbitrum-mainnet.json @@ -0,0 +1,7 @@ +{ + "Network": "arbitrum-one", + "LTokenSignaler_Address": "0x011C5B18aBC74A341209b12D1A6fD7B59E423428", + "LTokenSignaler_StartBlock": "1756244", + "LDYStaking_Address": "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137", + "LDYStaking_StartBlock": "218746026" +} diff --git a/subgraph/generated/LTokenSignaler/LToken.ts b/subgraph/generated/LTokenSignaler/LToken.ts index 7d510ef9..a3ea2eb1 100644 --- a/subgraph/generated/LTokenSignaler/LToken.ts +++ b/subgraph/generated/LTokenSignaler/LToken.ts @@ -1275,6 +1275,29 @@ export class LToken extends ethereum.SmartContract { let value = result.value; return ethereum.CallResult.fromValue(value[0].toAddress()); } + + withdrwalFeeInEth(): BigInt { + let result = super.call( + "withdrwalFeeInEth", + "withdrwalFeeInEth():(uint256)", + [], + ); + + return result[0].toBigInt(); + } + + try_withdrwalFeeInEth(): ethereum.CallResult { + let result = super.tryCall( + "withdrwalFeeInEth", + "withdrwalFeeInEth():(uint256)", + [], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBigInt()); + } } export class ApproveCall extends ethereum.Call { @@ -1939,6 +1962,36 @@ export class SetWithdrawerCall__Outputs { } } +export class SetWithdrwalFeeInEthCall extends ethereum.Call { + get inputs(): SetWithdrwalFeeInEthCall__Inputs { + return new SetWithdrwalFeeInEthCall__Inputs(this); + } + + get outputs(): SetWithdrwalFeeInEthCall__Outputs { + return new SetWithdrwalFeeInEthCall__Outputs(this); + } +} + +export class SetWithdrwalFeeInEthCall__Inputs { + _call: SetWithdrwalFeeInEthCall; + + constructor(call: SetWithdrwalFeeInEthCall) { + this._call = call; + } + + get withdrwalFeeInEth_(): BigInt { + return this._call.inputValues[0].value.toBigInt(); + } +} + +export class SetWithdrwalFeeInEthCall__Outputs { + _call: SetWithdrwalFeeInEthCall; + + constructor(call: SetWithdrwalFeeInEthCall) { + this._call = call; + } +} + export class StartRewardsRedirectionCall extends ethereum.Call { get inputs(): StartRewardsRedirectionCall__Inputs { return new StartRewardsRedirectionCall__Inputs(this); diff --git a/subgraph/generated/templates/LToken/LToken.ts b/subgraph/generated/templates/LToken/LToken.ts index 7d510ef9..a3ea2eb1 100644 --- a/subgraph/generated/templates/LToken/LToken.ts +++ b/subgraph/generated/templates/LToken/LToken.ts @@ -1275,6 +1275,29 @@ export class LToken extends ethereum.SmartContract { let value = result.value; return ethereum.CallResult.fromValue(value[0].toAddress()); } + + withdrwalFeeInEth(): BigInt { + let result = super.call( + "withdrwalFeeInEth", + "withdrwalFeeInEth():(uint256)", + [], + ); + + return result[0].toBigInt(); + } + + try_withdrwalFeeInEth(): ethereum.CallResult { + let result = super.tryCall( + "withdrwalFeeInEth", + "withdrwalFeeInEth():(uint256)", + [], + ); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBigInt()); + } } export class ApproveCall extends ethereum.Call { @@ -1939,6 +1962,36 @@ export class SetWithdrawerCall__Outputs { } } +export class SetWithdrwalFeeInEthCall extends ethereum.Call { + get inputs(): SetWithdrwalFeeInEthCall__Inputs { + return new SetWithdrwalFeeInEthCall__Inputs(this); + } + + get outputs(): SetWithdrwalFeeInEthCall__Outputs { + return new SetWithdrwalFeeInEthCall__Outputs(this); + } +} + +export class SetWithdrwalFeeInEthCall__Inputs { + _call: SetWithdrwalFeeInEthCall; + + constructor(call: SetWithdrwalFeeInEthCall) { + this._call = call; + } + + get withdrwalFeeInEth_(): BigInt { + return this._call.inputValues[0].value.toBigInt(); + } +} + +export class SetWithdrwalFeeInEthCall__Outputs { + _call: SetWithdrwalFeeInEthCall; + + constructor(call: SetWithdrwalFeeInEthCall) { + this._call = call; + } +} + export class StartRewardsRedirectionCall extends ethereum.Call { get inputs(): StartRewardsRedirectionCall__Inputs { return new StartRewardsRedirectionCall__Inputs(this); diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index a3af7c02..7fe6752e 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -6,11 +6,11 @@ schema: dataSources: - kind: ethereum/contract name: LTokenSignaler - network: mainnet + network: arbitrum-one source: - address: "0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e" + address: "0x011C5B18aBC74A341209b12D1A6fD7B59E423428" abi: LTokenSignaler - startBlock: 20008643 + startBlock: 1756244 mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -28,11 +28,11 @@ dataSources: handler: handleSignaledLToken - kind: ethereum name: LdyStaking - network: mainnet + network: arbitrum-one source: - address: "0x2AeDFB927Aa2aE87c220b9071c0A1209786b5C5e" + address: "0x98002b5c06b44c8769dA3DAe97CA498aB6F97137" abi: LdyStaking - startBlock: 20008643 + startBlock: 218746026 mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -58,7 +58,7 @@ dataSources: templates: - kind: ethereum/contract name: LToken - network: mainnet + network: arbitrum-one source: abi: LToken mapping: