diff --git a/.DS_Store b/.DS_Store index 0110b5a..7f7feba 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/contracts/.DS_Store b/contracts/.DS_Store index 2f57083..c2d6192 100644 Binary files a/contracts/.DS_Store and b/contracts/.DS_Store differ diff --git a/contracts/EsBAVA.sol b/contracts/EsBAVA.sol new file mode 100644 index 0000000..f950cdb --- /dev/null +++ b/contracts/EsBAVA.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.18; + +import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +contract EsBAVA is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, ERC20PausableUpgradeable, AccessControlUpgradeable, ERC20PermitUpgradeable, UUPSUpgradeable { + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE"); + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize(address defaultAdmin, address pauser, address minter, address upgrader) + initializer public + { + __ERC20_init("Escrowed BAVA", "esBAVA"); + __ERC20Burnable_init(); + __ERC20Pausable_init(); + __AccessControl_init(); + __ERC20Permit_init("Escrowed BAVA"); + __UUPSUpgradeable_init(); + + _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); + _grantRole(PAUSER_ROLE, pauser); + _grantRole(MINTER_ROLE, minter); + _grantRole(UPGRADER_ROLE, upgrader); + } + + function pause() public onlyRole(PAUSER_ROLE) { + _pause(); + } + + function unpause() public onlyRole(PAUSER_ROLE) { + _unpause(); + } + + function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) { + _mint(to, amount); + } + + function _authorizeUpgrade(address newImplementation) + internal + onlyRole(UPGRADER_ROLE) + override + {} + + // The following functions are overrides required by Solidity. + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal + whenNotPaused + override(ERC20Upgradeable, ERC20PausableUpgradeable) + { + super._beforeTokenTransfer(from, to, amount); + } +} \ No newline at end of file diff --git a/contracts/MultiCall.sol b/contracts/MultiCall.sol index 4c826b4..aa786e3 100644 --- a/contracts/MultiCall.sol +++ b/contracts/MultiCall.sol @@ -28,6 +28,12 @@ contract MultiCall is uint256 delegationReward; } + struct ValidatorUserDelegationInfo { + string validator; + uint256 delegationAmount; + uint256 allowanceShares; + } + /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); @@ -56,6 +62,27 @@ contract MultiCall is } } + /** + * @dev Get All Validator User Delegation + */ + function getAllValidatorUserDelegation(address user) external view returns (ValidatorUserDelegationInfo[] memory validatorUserDelegations) { + uint256 validatorsLength = IStakeFXVault(stFX).getValLength(); + + validatorUserDelegations = new ValidatorUserDelegationInfo[](validatorsLength); + for (uint256 i = 0; i < validatorsLength; i++) { + (, string memory validatorAddress) = IStakeFXVault(stFX).getValInfo(i); + + (, uint256 delegationAmount) = _delegation(validatorAddress, user); + uint256 allowanceShares = _allowanceShares(validatorAddress, user, stFX); + + validatorUserDelegations[i] = ValidatorUserDelegationInfo({ + validator: validatorAddress, + delegationAmount: delegationAmount, + allowanceShares: allowanceShares + }); + } + } + /**************************************** Only Owner Functions ****************************************/ function updateStFX( diff --git a/contracts/RewardDistributor.sol b/contracts/RewardDistributor.sol index c02f2dc..1ea3baf 100644 --- a/contracts/RewardDistributor.sol +++ b/contracts/RewardDistributor.sol @@ -72,8 +72,17 @@ contract RewardDistributor is Initializable, UUPSUpgradeable, IRewardDistributor emit TokensPerIntervalChange(_amount); } + + /**************************************** Only Owner Functions ****************************************/ + /** + * @dev Need to make sure all rewardTracker contracts fully migrate rewardToken to new rewardToken after update this contract rewardToken address + */ + function updateRewardToken(address _rewardToken) external onlyRole(OWNER_ROLE) { + rewardToken = _rewardToken; + } + function recoverToken( address token, uint256 amount, diff --git a/contracts/StakeFXVault.sol b/contracts/StakeFXVault.sol index 4a23dee..4b11b32 100644 --- a/contracts/StakeFXVault.sol +++ b/contracts/StakeFXVault.sol @@ -44,7 +44,7 @@ contract StakeFXVault is VaultInfo public vaultInfo; // Vault Info mapping(uint256 => ValInfo) public valInfo; // Validator info - mapping (address => UserInfo) public userInfo; // User info + mapping(address => UserInfo) public userInfo; // User info mapping(string => bool) public addedValidator; // True if validator is added struct VaultInfo { diff --git a/contracts/StakeFXVaultV2.sol b/contracts/StakeFXVaultV2.sol new file mode 100644 index 0000000..6f76a31 --- /dev/null +++ b/contracts/StakeFXVaultV2.sol @@ -0,0 +1,711 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.18; + +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import {MathUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + +import {IVestedFX} from "./interfaces/IVestedFX.sol"; +import {IRewardDistributor} from "./interfaces/IRewardDistributor.sol"; +import {IWFX} from "./interfaces/IWFX.sol"; +import {BaseVault} from "./vaults/BaseVault.sol"; +import {PrecompileStaking} from "./imp/PrecompileStaking.sol"; + +contract StakeFXVaultV2 is + Initializable, + UUPSUpgradeable, + PrecompileStaking, + ReentrancyGuardUpgradeable, + BaseVault +{ + using SafeERC20Upgradeable for IERC20Upgradeable; + using MathUpgradeable for uint256; + + uint256 internal constant BIPS_DIVISOR = 10000; + uint256 internal constant PRECISION = 1e30; + // address constant WFX = 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; // WFX mainnet: 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; WFX testnet: 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19 + + uint256 public pendingFxReward; // FX delegation rewards inside the contract pending for compound + uint256 public feeOnReward; // Compound reward protocol fee + uint256 public feeOnCompounder; // Compound reward compounder fee + uint256 public feeOnWithdrawal; // Withdrawal fee + address public vestedFX; // Contract that stored user's withdrawal info + address public feeTreasury; // Contract that keep compound reward fee + address public distributor; // Reward token distributor + + uint256 private MIN_COMPOUND_AMOUNT; // Minimum reward amount to compound when stake happen + uint256 private CAP_STAKE_FX_TARGET; // Cap amount of stFX + uint256 private STAKE_FX_TARGET; // Target stake amount to do whole validator list delegate + uint256 private UNSTAKE_FX_TARGET; // Target unstake amount to split undelegate + + VaultInfo public vaultInfo; // Vault Info + mapping(uint256 => ValInfo) public valInfo; // Validator info + mapping(address => UserInfo) public userInfo; // User info + mapping(string => bool) public addedValidator; // True if validator is added + + address constant WFX = 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19; // WFX mainnet: 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; WFX testnet: 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19 + + struct VaultInfo { + uint256 stakeId; + uint256 unstakeId; + uint256 length; + uint256 totalAllocPoint; + uint256 cumulativeRewardPerToken; + } + + struct ValInfo { + uint256 allocPoint; + string validator; + } + + struct UserInfo { + uint256 claimableReward; + uint256 previousCumulatedRewardPerToken; + } + + event Stake(address indexed user, uint256 amount, uint256 shares); + event Unstake(address indexed user, uint256 amount, uint256 shares); + event Compound(address indexed user, uint256 compoundAmount); + event Claim(address receiver, uint256 amount); + event ValidatorAdded(string val, uint256 newAllocPoint); + event ValidatorRemoved(string val); + event ValidatorUpdated(string val, uint256 newAllocPoint); + event VestedFXChanged(address newAddress); + event FeeTreasuryChanged(address newAddress); + event DistributorChanged(address newAddress); + event ValidatorRedelegated(string srcVal, string dstVal, uint256 sharesAmount, uint256 redelegatedShares); + + receive() external payable {} + + modifier onlyVestedFX() { + require(msg.sender == vestedFX, "Only VestedFX can call"); + _; + } + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /****************************************** Core External Functions ******************************************/ + /** + * @notice user stake FX to this contract + */ + function stake() external payable nonReentrant whenNotPaused { + require(msg.value > 0, "Stake: 0 amount"); + uint256 totalAsset = totalAssets(); + require(msg.value + totalAsset <= CAP_STAKE_FX_TARGET, "Stake: > Cap"); + + uint256 delegationReward = getTotalDelegationRewards(); + if(delegationReward >= MIN_COMPOUND_AMOUNT) { + _compound(); + } + _claim(msg.sender, msg.sender); + + uint256 shares = previewDeposit(msg.value); + _mint(msg.sender, shares); + + _stake(msg.value); + + emit Stake(msg.sender, msg.value, shares); + } + + /** + * @notice user stake WFX to this contract + */ + function stakeWFX(uint256 amount) external nonReentrant whenNotPaused { + require(amount > 0, "Stake: 0 amount"); + uint256 totalAsset = totalAssets(); + require(amount + totalAsset <= CAP_STAKE_FX_TARGET, "Stake: > Cap"); + + uint256 delegationReward = getTotalDelegationRewards(); + if(delegationReward >= MIN_COMPOUND_AMOUNT) { + _compound(); + } + _claim(msg.sender, msg.sender); + + IWFX(WFX).transferFrom(msg.sender, address(this), amount); + IWFX(WFX).withdraw(payable(address(this)), amount); + + uint256 shares = previewDeposit(amount); + _mint(msg.sender, shares); + + _stake(amount); + + emit Stake(msg.sender, amount, shares); + } + + /** + * @notice user unstake/ request undelegate FX + * @param amount User's fx-LP receipt tokens + */ + function unstake(uint256 amount) external whenNotPaused { + require(amount > 0, "Unstake: 0 amount"); + uint256 sharesBalance = balanceOf(msg.sender); + require(sharesBalance >= amount, "Amount > stake"); + + // Add compound if contract size allow + uint256 delegationReward = getTotalDelegationRewards(); + if(delegationReward >= MIN_COMPOUND_AMOUNT) { + _compound(); + } + _claim(msg.sender, msg.sender); + + uint256 undelegateAmount = previewRedeem(amount); + uint256 undelegateAmountAfterFee = undelegateAmount * (BIPS_DIVISOR - feeOnWithdrawal) / BIPS_DIVISOR; + + _burn(msg.sender, amount); + if (undelegateAmountAfterFee > 0) { + _unstake(undelegateAmountAfterFee); + } + + emit Unstake(msg.sender, undelegateAmountAfterFee, amount); + } + + /** + * @notice transfer user delegation shares to this contract + * @param val validator address + * @param amount Amount of user's delegate shares transferred to this contract + */ + function entrustDelegatedShare(string memory val, uint256 amount) external nonReentrant whenNotPaused { + require(amount > 0, "Entrust: 0 share"); + + (uint256 sharesAmount, uint256 delegationAmount) = _delegation(val, msg.sender); + require(sharesAmount >= amount, "Not enough share"); + + uint256 delegationReward = getTotalDelegationRewards(); + if(delegationReward >= MIN_COMPOUND_AMOUNT) { + _compound(); + } + _claim(msg.sender, msg.sender); + + uint256 totalAsset = totalAssets(); + uint256 estimateDelegateAmount = amount / sharesAmount * delegationAmount; + require(estimateDelegateAmount + totalAsset <= CAP_STAKE_FX_TARGET, "Stake: > Cap"); + + uint256 supply = totalSupply(); + (uint256 fxAmountToTransfer, uint256 returnReward) = _transferFromShares(val, msg.sender, address(this), amount); + + pendingFxReward += returnReward; + + uint256 shares = (fxAmountToTransfer == 0 || supply == 0) + ? _initialConvertToShares(fxAmountToTransfer, MathUpgradeable.Rounding.Down) + : fxAmountToTransfer.mulDiv(supply, totalAsset, MathUpgradeable.Rounding.Down); + + _mint(msg.sender, shares); + + emit Stake(msg.sender, fxAmountToTransfer, shares); + } + + function claim(address receiver) external nonReentrant returns (uint256) { + return _claim(msg.sender, receiver); + } + + /** + * @notice compound delegation rewards + */ + function compound() external nonReentrant whenNotPaused { + _compound(); + } + + function sendVestedFX( + uint256 safeAmount + ) external onlyVestedFX { + address recipient = payable(msg.sender); + (bool success, ) = recipient.call{value: safeAmount}(""); + require(success, "Failed to send FX"); + } + + function updateRewards() external nonReentrant { + _updateRewards(address(0)); + } + + /**************************************** Internal and Private Functions ****************************************/ + + /** + * @dev Helper function to delegate FX amount to validators. + * @param amount The amount: FX delegate to validators. + */ + function _stake(uint256 amount) internal { + VaultInfo memory vault = vaultInfo; + uint256 totalAllocPoint = vault.totalAllocPoint; + uint256 index = vault.stakeId; + uint256 vaultLength = vault.length; + uint256 totalReturnReward; + uint256 _totalAssets = totalAssets(); + + // After execute removeValidator, stakeId may equal or greater than vaultLength + if (index >= vaultLength) { + index = 0; + } + + uint256 numValidators = _calculateNumberofValidators(amount); + uint256 amountPerValidator = amount / numValidators; + uint256 remainingAmount = amount; + uint256 delegateAmount; + + while (remainingAmount != 0) { + ValInfo memory val = valInfo[index]; + uint256 allocPoint = val.allocPoint; + index = (index + 1) % vaultLength; + + if (allocPoint == 0) { + continue; + } + + if (_totalAssets >= CAP_STAKE_FX_TARGET) { + delegateAmount = remainingAmount; + } else { + (, uint256 delegationAmount) = _delegation(val.validator, address(this)); + uint256 maxValSize = allocPoint * CAP_STAKE_FX_TARGET / totalAllocPoint; + + if (delegationAmount >= maxValSize) { + continue; + } + + if (remainingAmount <= amountPerValidator) { + delegateAmount = remainingAmount; + } else { + delegateAmount = amountPerValidator; + } + } + + (, uint256 returnReward) = _delegate(val.validator, delegateAmount); + _totalAssets += delegateAmount; + totalReturnReward += returnReward; + remainingAmount -= delegateAmount; + } + + vaultInfo.stakeId = index; + pendingFxReward += totalReturnReward; + } + + /** + * @dev Helper function to undelegate FX amount from validators. + * @param amount The amount: FX to unstake from the vault. + */ + function _unstake(uint256 amount) internal { + VaultInfo memory vault = vaultInfo; + uint256 index = vault.unstakeId; + uint256 vaultLength = vault.length; + + uint256 remainingAmount = amount; + uint256 totalReward; + uint256 returnUndelegatedAmount; + uint256 returnReward; + uint256 endTime; + + // After execute removeValidator, stakeId may equal or greater than vaultLength + if (index >= vaultLength) { + index = 0; + } + // If contract byte size exceed limit, divide to half part can be removed + if (amount >= UNSTAKE_FX_TARGET) { + uint256 halfOfUndelegateAmount = amount / 2; + (returnUndelegatedAmount, returnReward, endTime) = _toUndelegate(index, halfOfUndelegateAmount); + + remainingAmount -= returnUndelegatedAmount; + index = (index + 1) % vaultLength; + totalReward += returnReward; + } + + while (remainingAmount != 0) { + (returnUndelegatedAmount, returnReward, endTime) = _toUndelegate(index, remainingAmount); + + remainingAmount -= returnUndelegatedAmount; + index = (index + 1) % vaultLength; + totalReward += returnReward; + } + + IVestedFX(vestedFX).lockWithEndTime( + msg.sender, + amount, + endTime + ); + + vaultInfo.unstakeId = index; + pendingFxReward += totalReward; + } + + /** + * @dev Helper function to undelegate FX amount from validators. + * @param index Validator ID in validator list. + * @param remainingAmount Amount to undelegate from validators. + */ + function _toUndelegate(uint256 index, uint256 remainingAmount) internal returns(uint256, uint256, uint256) { + (uint256 sharesAmount, uint256 delegationAmount) = _delegation(valInfo[index].validator, address(this)); + + uint256 amountToUndelegate; + uint256 returnReward; + uint256 endTime; + + if (delegationAmount > 0) { + if (delegationAmount >= remainingAmount) { + amountToUndelegate = remainingAmount; + } else { + amountToUndelegate = delegationAmount; + } + + uint256 shareToWithdraw = (sharesAmount * amountToUndelegate) / delegationAmount; + if (shareToWithdraw > 0) { + (amountToUndelegate, returnReward, endTime) = _undelegate(valInfo[index].validator, shareToWithdraw); + } + } + + return (amountToUndelegate, returnReward, endTime); + } + + /** + * @dev Helper function to compound FX amount from validators. + */ + function _compound() internal { + uint256 delegateReward = _withdrawReward() + pendingFxReward; + pendingFxReward = 0; + + uint256 feeProtocol = (delegateReward * feeOnReward) / BIPS_DIVISOR; + uint256 feeCompounder = (delegateReward * feeOnCompounder) / BIPS_DIVISOR; + + delegateReward = delegateReward - feeProtocol - feeCompounder; + _stake(delegateReward); + + address treasury = payable(feeTreasury); + address user = payable(msg.sender); + (bool successTreasury, ) = treasury.call{value: feeProtocol}(""); + (bool successUser, ) = user.call{value: feeCompounder}(""); + require(successTreasury && successUser, "Failed to send FX"); + + emit Compound(msg.sender, delegateReward); + } + + /** + * @dev Helper function to withdraw delegation fx rewards from all validators. + */ + function _withdrawReward() internal returns (uint256) { + VaultInfo memory vault = vaultInfo; + uint256 reward = 0; + + uint256 vaultLength = vault.length; + + for (uint256 i; i < vaultLength; i++) { + string memory validator = valInfo[i].validator; + uint256 delegationReward = _delegationRewards(validator, address(this)); + if(delegationReward > 0) { + uint256 returnReward = _withdraw(validator); + reward += returnReward; + } + } + + return reward; + } + + /** + * @dev Helper function to help to calculate number of validator to delegate based on Log10 input amount. + * @param delegateAmount Fx Amount to stake. + * @return Number of validators to delegate. + */ + function _calculateNumberofValidators( + uint256 delegateAmount + ) internal view returns (uint256) { + uint256 numValidators; + uint256 delegateAmountInEther = delegateAmount / 10**18; + + uint256 valLength = getValLength(); + while (delegateAmountInEther >= 10) { + delegateAmountInEther /= 10; + numValidators++; + } + + return (numValidators == 0) ? 1 : (numValidators > valLength + ? valLength + : numValidators); + } + + /** + * @dev Helper function to help to query total FX delegation. + */ + function _getUnderlyingFX() internal view returns (uint256) { + uint256 totalAmount; + uint256 valLength = getValLength(); + for (uint256 i; i < valLength; i++) { + string memory validator = valInfo[i].validator; + (, uint256 delegationAmount) = _delegation(validator, address(this)); + totalAmount += delegationAmount; + } + return totalAmount; + } + + function _claim(address account, address receiver) private returns (uint256) { + _updateRewards(account); + UserInfo storage user = userInfo[account]; + uint256 tokenAmount = user.claimableReward; + user.claimableReward = 0; + + if (tokenAmount > 0) { + IERC20Upgradeable(rewardToken()).safeTransfer(receiver, tokenAmount); + emit Claim(account, tokenAmount); + } + + return tokenAmount; + } + + function _updateRewards(address account) private { + uint256 blockReward = IRewardDistributor(distributor).distribute(); + + uint256 supply = totalSupply(); + uint256 _cumulativeRewardPerToken = vaultInfo.cumulativeRewardPerToken; + if (supply > 0 && blockReward > 0) { + _cumulativeRewardPerToken = _cumulativeRewardPerToken + (blockReward * (PRECISION) / (supply)); + vaultInfo.cumulativeRewardPerToken = _cumulativeRewardPerToken; + } + + // cumulativeRewardPerToken can only increase + // so if cumulativeRewardPerToken is zero, it means there are no rewards yet + if (_cumulativeRewardPerToken == 0) { + return; + } + + if (account != address(0)) { + UserInfo storage user = userInfo[account]; + uint256 stakedAmount = balanceOf(account); + uint256 accountReward = stakedAmount * (_cumulativeRewardPerToken - (user.previousCumulatedRewardPerToken)) / (PRECISION); + uint256 _claimableReward = user.claimableReward + (accountReward); + + user.claimableReward = _claimableReward; + user.previousCumulatedRewardPerToken = _cumulativeRewardPerToken; + } + } + + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal + whenNotPaused + override + { + _updateRewards(from); + _updateRewards(to); + + super._beforeTokenTransfer(from, to, amount); + } + + function _authorizeUpgrade( + address + ) internal override onlyRole(OWNER_ROLE) {} + + + /**************************************** Public/External View Functions ****************************************/ + + /** + * @notice Return total asset(FX) deposited + * @return Amount of asset(FX) deposited + */ + function totalAssets() public view override returns (uint256) { + uint256 underlying = _getUnderlyingFX(); + return underlying; + } + + function getValLength() public view returns (uint256) { + return vaultInfo.length; + } + + /** + * @notice Return validator address and allocPoint + */ + function getValInfo(uint256 index) public view returns (uint256, string memory) { + return (valInfo[index].allocPoint, valInfo[index].validator); + } + + /** + * @notice Return total delegation reward + */ + function getTotalDelegationRewards() public view returns (uint256) { + uint256 totalAmount; + uint256 valLength = getValLength(); + for (uint256 i; i < valLength; i++) { + string memory validator = valInfo[i].validator; + uint256 delegationReward = _delegationRewards(validator, address(this)); + totalAmount += delegationReward; + } + return totalAmount + pendingFxReward; + } + + function getVaultConfigs() public view returns (uint256, uint256, uint256, uint256) { + return (MIN_COMPOUND_AMOUNT, CAP_STAKE_FX_TARGET, UNSTAKE_FX_TARGET, STAKE_FX_TARGET); + } + + function rewardToken() public view returns (address) { + return IRewardDistributor(distributor).rewardToken(); + } + + function claimable(address account) public view returns (uint256) { + UserInfo memory user = userInfo[account]; + uint256 stakedAmount = balanceOf(account); + if (stakedAmount == 0) { + return user.claimableReward; + } + uint256 supply = totalSupply(); + uint256 pendingRewards = IRewardDistributor(distributor).pendingRewards() * (PRECISION); + uint256 nextCumulativeRewardPerToken = vaultInfo.cumulativeRewardPerToken + (pendingRewards / (supply)); + return user.claimableReward + ( + stakedAmount * (nextCumulativeRewardPerToken - (user.previousCumulatedRewardPerToken)) / (PRECISION)); + } + + /**************************************** Only Governor Functions ****************************************/ + + function addValidator( + string memory _validator, + uint256 _allocPoint + ) external onlyRole(GOVERNOR_ROLE) { + require(addedValidator[_validator] == false, "addedVal"); + valInfo[vaultInfo.length].validator = _validator; + valInfo[vaultInfo.length].allocPoint = _allocPoint; + + vaultInfo.length++; + vaultInfo.totalAllocPoint += _allocPoint; + + addedValidator[_validator]=true; + + emit ValidatorAdded(_validator, _allocPoint); + } + + /** + * @notice remove validators which has 0 allocPoint and 0 delegation in the list + */ + function removeValidator() external onlyRole(GOVERNOR_ROLE) { + VaultInfo memory vault = vaultInfo; + uint256 vaultLength = vault.length; + + for (uint256 i = 0; i < vaultLength;) { + if (valInfo[i].allocPoint == 0) { + string memory val = valInfo[i].validator; + (uint256 sharesAmount, ) = _delegation(val, address(this)); + + if (sharesAmount == 0) { + addedValidator[val] = false; + uint256 lastIndex = vaultLength - 1; + valInfo[i] = valInfo[lastIndex]; + delete valInfo[lastIndex]; + + emit ValidatorRemoved(val); + vaultLength--; + // Skip if i == 0 to prevent underflow + if (i == 0) { + continue; + } else { + --i; + } + } + } + unchecked { + ++i; + } + } + + vaultInfo.length = vaultLength; + } + + function redelegateValidator( + uint256 srcId, + uint256 dstId, + uint256 redelegateAmount + ) external onlyRole(GOVERNOR_ROLE) { + require(srcId < vaultInfo.length && dstId < vaultInfo.length, "Invalid ID"); + ValInfo memory srcVal = valInfo[srcId]; + ValInfo memory dstVal = valInfo[dstId]; + (uint256 sharesAmount,) = _delegation(srcVal.validator, address(this)); + + uint256 returnReward; + uint256 redelegatedShares; + + require(redelegateAmount <= sharesAmount, "!Amount"); + (redelegatedShares, returnReward, ) = _redelegate(srcVal.validator, dstVal.validator, redelegateAmount); + + pendingFxReward += returnReward; + + emit ValidatorRedelegated(srcVal.validator, dstVal.validator, sharesAmount, redelegatedShares); + } + + function updateValidator( + uint256 id, + uint256 newAllocPoint + ) external onlyRole(GOVERNOR_ROLE) { + require(id < vaultInfo.length, "Invalid ID"); + uint256 oldAllocPoint = valInfo[id].allocPoint; + + vaultInfo.totalAllocPoint = vaultInfo.totalAllocPoint + newAllocPoint - oldAllocPoint; + valInfo[id].allocPoint = newAllocPoint; + + emit ValidatorUpdated(valInfo[id].validator, newAllocPoint); + } + + function updateConfigs(uint256 newMinCompound, uint256 newCapStakeFxTarget, uint256 newUnstakeFxTarget, uint256 newStakeFxTarget) external onlyRole(GOVERNOR_ROLE) { + MIN_COMPOUND_AMOUNT = newMinCompound; + CAP_STAKE_FX_TARGET = newCapStakeFxTarget; + UNSTAKE_FX_TARGET = newUnstakeFxTarget; + STAKE_FX_TARGET = newStakeFxTarget; + } + + /** + * @notice Update compounding fee percentage for protocol and compounder and user withdrawal percentage + * newFeeOnReward + newFeeOnCompounder) <= BIPS_DIVISOR && newFeeOnWithdrawal <= BIPS_DIVISOR + */ + function updateFees(uint256 newFeeOnReward, uint256 newFeeOnCompounder, uint256 newFeeOnWithdrawal) external onlyRole(GOVERNOR_ROLE) { + feeOnReward = newFeeOnReward; + feeOnCompounder = newFeeOnCompounder; + feeOnWithdrawal = newFeeOnWithdrawal; + } + + /**************************************** Only Owner Functions ****************************************/ + + function updateVestedFX(address newAddress) external onlyRole(OWNER_ROLE) { + vestedFX = newAddress; + emit VestedFXChanged(newAddress); + } + + function updateFeeTreasury(address newAddress) external onlyRole(OWNER_ROLE) { + feeTreasury = newAddress; + emit FeeTreasuryChanged(newAddress); + } + + function updateDistributor(address newAddress) external onlyRole(OWNER_ROLE) { + distributor = newAddress; + emit DistributorChanged(newAddress); + } + + function recoverToken( + address token, + uint256 amount, + address _recipient + ) external onlyRole(OWNER_ROLE) { + require(_recipient != address(0), "Send to zero address"); + if(token != address(0)) { + IERC20Upgradeable(token).safeTransfer(_recipient, amount); + } else { + address recipient = payable(_recipient); + (bool success, ) = recipient.call{value: amount}(""); + require(success, "Failed to send FX"); + } + } + + /************************************************************** + * @dev Initialize the states + *************************************************************/ + + function initialize( + address _asset, + address _owner, + address _governor + ) public initializer { + __BaseVaultInit( + _asset, + "Staked FX Token", + "StFX", + _owner, + _governor + ); + // __Governable_init(_owner, _governor); redundant code + __UUPSUpgradeable_init(); + } +} \ No newline at end of file diff --git a/contracts/StakeFXVaultV3.sol b/contracts/StakeFXVaultV3.sol new file mode 100644 index 0000000..1a61f40 --- /dev/null +++ b/contracts/StakeFXVaultV3.sol @@ -0,0 +1,667 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.18; + +import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; +import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import {MathUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + +import {IVestedFX} from "./interfaces/IVestedFX.sol"; +import {IRewardDistributor} from "./interfaces/IRewardDistributor.sol"; +import {IWFX} from "./interfaces/IWFX.sol"; +import {BaseVault} from "./vaults/BaseVault.sol"; +import {PrecompileStaking} from "./imp/PrecompileStaking.sol"; + +contract StakeFXVaultV3 is + Initializable, + UUPSUpgradeable, + PrecompileStaking, + ReentrancyGuardUpgradeable, + BaseVault +{ + using SafeERC20Upgradeable for IERC20Upgradeable; + using MathUpgradeable for uint256; + + uint256 internal constant BIPS_DIVISOR = 10000; + uint256 internal constant PRECISION = 1e30; + // address constant WFX = 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; // WFX mainnet: 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; WFX testnet: 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19 + + uint256 public pendingFxReward; // FX delegation rewards inside the contract pending for compound + uint256 public feeOnReward; // Compound reward protocol fee + uint256 public feeOnCompounder; // Compound reward compounder fee + uint256 public feeOnWithdrawal; // Withdrawal fee + address public vestedFX; // Contract that stored user's withdrawal info + address public feeTreasury; // Contract that keep compound reward fee + address public distributor; // Reward token distributor + + uint256 private MIN_COMPOUND_AMOUNT; // Minimum reward amount to compound when stake happen + uint256 private CAP_STAKE_FX_TARGET; // Cap amount of stFX + uint256 private STAKE_FX_TARGET; // Target stake amount to do whole validator list delegate(Deprecated) + uint256 private UNSTAKE_FX_TARGET; // Target unstake amount to split undelegate(Deprecated) + + VaultInfo public vaultInfo; // Vault Info + mapping(uint256 => ValInfo) public valInfo; // Validator info + mapping(address => UserInfo) public userInfo; // User info + mapping(string => bool) public addedValidator; // True if validator is added + + address constant WFX = 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19; // WFX mainnet: 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; WFX testnet: 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19 + + struct VaultInfo { + uint256 stakeId; + uint256 unstakeId; + uint256 length; + uint256 totalAllocPoint; + uint256 cumulativeRewardPerToken; + } + + struct ValInfo { + uint256 allocPoint; + string validator; + } + + struct UserInfo { + uint256 claimableReward; + uint256 previousCumulatedRewardPerToken; + } + + event Stake(address indexed user, uint256 amount, uint256 shares); + event Unstake(address indexed user, uint256 amount, uint256 shares); + event Compound(address indexed user, uint256 compoundAmount); + event Claim(address receiver, uint256 amount); + event ValidatorAdded(string val, uint256 newAllocPoint); + event ValidatorRemoved(string val); + event ValidatorUpdated(string val, uint256 newAllocPoint); + event VestedFXChanged(address newAddress); + event FeeTreasuryChanged(address newAddress); + event DistributorChanged(address newAddress); + event ValidatorRedelegated(string srcVal, string dstVal, uint256 sharesAmount, uint256 redelegatedShares); // last 2 arguments changed to FxAmount in staking V2 + + receive() external payable {} + + modifier onlyVestedFX() { + require(msg.sender == vestedFX, "Only VestedFX can call"); + _; + } + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + /****************************************** Core External Functions ******************************************/ + /** + * @notice user stake FX/WFX to this contract + * @param amount stake amount + * @param native stake FX or WFX token + */ + function stake(uint256 amount, bool native) external payable nonReentrant whenNotPaused { + require(amount > 0, "Stake: 0 amount"); + require(msg.value == (native == true ? amount : 0), "!valid"); + require(amount + totalAssets() <= CAP_STAKE_FX_TARGET, "Stake: > Cap"); + + // Skip check delegation reward to save gas + _compound(); + _claim(msg.sender, msg.sender); + + if(native == false) { + IWFX(WFX).transferFrom(msg.sender, address(this), amount); + IWFX(WFX).withdraw(payable(address(this)), amount); + } + + uint256 shares = previewDeposit(amount); + _mint(msg.sender, shares); + + _stake(amount); + + emit Stake(msg.sender, amount, shares); + } + + /** + * @notice user unstake(request undelegate FX) + * @param amount User's fx-LP receipt tokens + */ + function unstake(uint256 amount) external nonReentrant whenNotPaused { + require(amount > 0, "Unstake: 0 amount"); + uint256 sharesBalance = balanceOf(msg.sender); + require(sharesBalance >= amount, "Amount > stake"); + + _compound(); + _claim(msg.sender, msg.sender); + + uint256 undelegateAmount = previewRedeem(amount); + uint256 undelegateAmountAfterFee = undelegateAmount * (BIPS_DIVISOR - feeOnWithdrawal) / BIPS_DIVISOR; + + _burn(msg.sender, amount); + if (undelegateAmountAfterFee > 0) { + _unstake(undelegateAmountAfterFee); + } + + emit Unstake(msg.sender, undelegateAmountAfterFee, amount); + } + + /** + * @notice transfer user delegation shares to this contract + * @param val validator address + * @param amount Amount of user's delegate shares transferred to this contract + */ + function entrustDelegatedShare(string memory val, uint256 amount) external nonReentrant whenNotPaused { + require(amount > 0, "Entrust: 0 share"); + + (uint256 sharesAmount, uint256 delegationAmount) = _delegation(val, msg.sender); + require(sharesAmount >= amount, "Not enough share"); + + _compound(); + _claim(msg.sender, msg.sender); + + uint256 totalAsset = totalAssets(); + uint256 estimateDelegateAmount = amount / sharesAmount * delegationAmount; + require(estimateDelegateAmount + totalAsset <= CAP_STAKE_FX_TARGET, "Stake: > Cap"); + + uint256 supply = totalSupply(); + (uint256 fxAmountToTransfer, uint256 returnReward) = _transferFromShares(val, msg.sender, address(this), amount); + + pendingFxReward += returnReward; + + uint256 shares = (fxAmountToTransfer == 0 || supply == 0) + ? _initialConvertToShares(fxAmountToTransfer, MathUpgradeable.Rounding.Down) + : fxAmountToTransfer.mulDiv(supply, totalAsset, MathUpgradeable.Rounding.Down); + + _mint(msg.sender, shares); + + emit Stake(msg.sender, fxAmountToTransfer, shares); + } + + function claim(address receiver) external nonReentrant returns (uint256) { + return _claim(msg.sender, receiver); + } + + /** + * @notice compound delegation rewards + */ + function compound() external nonReentrant whenNotPaused { + _compound(); + } + + function updateRewards() external nonReentrant { + _updateRewards(address(0)); + } + + function sendVestedFX( + uint256 safeAmount + ) external onlyVestedFX { + address recipient = payable(msg.sender); + (bool success, ) = recipient.call{value: safeAmount}(""); + require(success, "Failed to send FX"); + } + + /**************************************** Internal and Private Functions ****************************************/ + /** + * @dev Helper function to delegate FX amount to validators. + * @param amount The amount: FX delegate to validators. + */ + function _stake(uint256 amount) internal { + VaultInfo memory vault = vaultInfo; + uint256 totalAllocPoint = vault.totalAllocPoint; + uint256 index = vault.stakeId; + + uint256 valLength = getValLength(); + uint256 _totalAssets = totalAssets(); + uint256 numValidators = _calculateNumberofValidators(amount); + uint256 amountPerValidator = amount / numValidators; + uint256 remainingAmount = amount; + uint256 delegateAmount; + + while (remainingAmount != 0) { + ValInfo memory val = valInfo[index]; + uint256 allocPoint = val.allocPoint; + index = (index + 1) % valLength; + + if (allocPoint == 0) { + continue; + } + + if (_totalAssets >= CAP_STAKE_FX_TARGET) { + delegateAmount = remainingAmount; + } else { + (, uint256 delegationAmount) = _delegation(val.validator, address(this)); + uint256 maxValSize = allocPoint * CAP_STAKE_FX_TARGET / totalAllocPoint; + + if (delegationAmount >= maxValSize) { + continue; + } + + if (remainingAmount <= amountPerValidator) { + delegateAmount = remainingAmount; + } else { + delegateAmount = amountPerValidator; + } + } + + bool result = _delegateV2(val.validator, delegateAmount); + require(result == true, "delegate fail"); + _totalAssets += delegateAmount; + remainingAmount -= delegateAmount; + } + + vaultInfo.stakeId = index; + } + + /** + * @dev Helper function to undelegate FX amount from validators. + * @param amount The amount: FX to unstake from the vault. + */ + function _unstake(uint256 amount) internal { + VaultInfo memory vault = vaultInfo; + uint256 index = vault.unstakeId; + uint256 valLength = getValLength(); + + uint256 remainingAmount = amount; + uint256 totalReward; + uint256 returnUndelegatedAmount; + uint256 returnReward; + + // If contract byte size exceed limit, divide to half part can be removed + if (amount >= UNSTAKE_FX_TARGET) { + uint256 halfOfUndelegateAmount = amount / 2; + (returnUndelegatedAmount) = _toUndelegate(index, halfOfUndelegateAmount); + + remainingAmount -= returnUndelegatedAmount; + index = (index + 1) % valLength; + totalReward += returnReward; + } + + while (remainingAmount != 0) { + (returnUndelegatedAmount) = _toUndelegate(index, remainingAmount); + + remainingAmount -= returnUndelegatedAmount; + index = (index + 1) % valLength; + totalReward += returnReward; + } + + IVestedFX(vestedFX).lockWithEndTime( + msg.sender, + amount, + block.timestamp + 21 days + ); + + vaultInfo.unstakeId = index; + pendingFxReward += totalReward; + } + + /** + * @dev Helper function to undelegate FX amount from validators. + * @param index Validator ID in validator list. + * @param remainingAmount Amount to undelegate from validators. + */ + function _toUndelegate(uint256 index, uint256 remainingAmount) internal returns(uint256) { + (, uint256 delegationAmount) = _delegation(valInfo[index].validator, address(this)); + + uint256 amountToUndelegate; + + if (delegationAmount > 0) { + if (delegationAmount >= remainingAmount) { + amountToUndelegate = remainingAmount; + } else { + amountToUndelegate = delegationAmount; + } + + _undelegateV2(valInfo[index].validator, amountToUndelegate); + } + + return amountToUndelegate; + } + + /** + * @dev Helper function to compound FX amount from validators. + */ + function _compound() internal { + _withdrawReward(); + uint256 delegateReward = pendingFxReward; + pendingFxReward = 0; + + uint256 feeProtocol = (delegateReward * feeOnReward) / BIPS_DIVISOR; + uint256 feeCompounder = (delegateReward * feeOnCompounder) / BIPS_DIVISOR; + + delegateReward = delegateReward - feeProtocol - feeCompounder; + _stake(delegateReward); + + address treasury = payable(feeTreasury); + address user = payable(msg.sender); + (bool successTreasury, ) = treasury.call{value: feeProtocol}(""); + (bool successUser, ) = user.call{value: feeCompounder}(""); + require(successTreasury && successUser, "Failed to send FX"); + + emit Compound(msg.sender, delegateReward); + } + + /** + * @dev Helper function to withdraw delegation fx rewards from all validators. + */ + function _withdrawReward() internal { + uint256 reward = 0; + uint256 valLength = getValLength(); + + for (uint256 i; i < valLength; i++) { + string memory validator = valInfo[i].validator; + uint256 delegationReward = _delegationRewards(validator, address(this)); + if(delegationReward > 0) { + uint256 returnReward = _withdraw(validator); + reward += returnReward; + } + } + + pendingFxReward += reward; + } + + /** + * @dev Helper function to help to calculate number of validator to delegate based on Log10 input amount. + * @param delegateAmount Fx Amount to stake. + * @return Number of validators to delegate. + */ + function _calculateNumberofValidators( + uint256 delegateAmount + ) internal view returns (uint256) { + uint256 numValidators; + uint256 delegateAmountInEther = delegateAmount / 10**18; + + uint256 valLength = getValLength(); + while (delegateAmountInEther >= 10) { + delegateAmountInEther /= 10; + numValidators++; + } + + return (numValidators == 0) ? 1 : (numValidators > valLength + ? valLength + : numValidators); + } + + /** + * @dev Helper function to help to query total FX delegation. + */ + function _getUnderlyingFX() internal view returns (uint256) { + uint256 totalAmount; + uint256 valLength = getValLength(); + for (uint256 i; i < valLength; i++) { + string memory validator = valInfo[i].validator; + (, uint256 delegationAmount) = _delegation(validator, address(this)); + totalAmount += delegationAmount; + } + return totalAmount; + } + + function _claim(address account, address receiver) private returns (uint256) { + _updateRewards(account); + UserInfo storage user = userInfo[account]; + uint256 tokenAmount = user.claimableReward; + user.claimableReward = 0; + + if (tokenAmount > 0) { + IERC20Upgradeable(rewardToken()).safeTransfer(receiver, tokenAmount); + emit Claim(account, tokenAmount); + } + + return tokenAmount; + } + + function _updateRewards(address account) private { + uint256 blockReward = IRewardDistributor(distributor).distribute(); + + uint256 supply = totalSupply(); + uint256 _cumulativeRewardPerToken = vaultInfo.cumulativeRewardPerToken; + if (supply > 0 && blockReward > 0) { + _cumulativeRewardPerToken = _cumulativeRewardPerToken + (blockReward * (PRECISION) / (supply)); + vaultInfo.cumulativeRewardPerToken = _cumulativeRewardPerToken; + } + + // cumulativeRewardPerToken can only increase + // so if cumulativeRewardPerToken is zero, it means there are no rewards yet + if (_cumulativeRewardPerToken == 0) { + return; + } + + if (account != address(0)) { + UserInfo storage user = userInfo[account]; + uint256 stakedAmount = balanceOf(account); + uint256 accountReward = stakedAmount * (_cumulativeRewardPerToken - (user.previousCumulatedRewardPerToken)) / (PRECISION); + uint256 _claimableReward = user.claimableReward + (accountReward); + + user.claimableReward = _claimableReward; + user.previousCumulatedRewardPerToken = _cumulativeRewardPerToken; + } + } + + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal + whenNotPaused + override + { + _updateRewards(from); + _updateRewards(to); + + super._beforeTokenTransfer(from, to, amount); + } + + function _authorizeUpgrade( + address + ) internal override onlyRole(OWNER_ROLE) {} + + + /**************************************** Public/External View Functions ****************************************/ + + /** + * @notice Return total asset(FX) deposited + * @return Amount of asset(FX) deposited + */ + function totalAssets() public view override returns (uint256) { + uint256 underlying = _getUnderlyingFX(); + return underlying; + } + + function getValLength() public view returns (uint256) { + return vaultInfo.length; + } + + /** + * @notice Return validator address and allocPoint + */ + function getValInfo(uint256 index) public view returns (uint256, string memory) { + return (valInfo[index].allocPoint, valInfo[index].validator); + } + + /** + * @notice Return total delegation reward + */ + function getTotalDelegationRewards() public view returns (uint256) { + uint256 totalAmount; + uint256 valLength = getValLength(); + for (uint256 i; i < valLength; i++) { + string memory validator = valInfo[i].validator; + uint256 delegationReward = _delegationRewards(validator, address(this)); + totalAmount += delegationReward; + } + return totalAmount + pendingFxReward; + } + + /** + * @notice Return vault config(remove STAKE_FX_TARGET) + */ + function getVaultConfigs() public view returns (uint256, uint256, uint256) { + return (MIN_COMPOUND_AMOUNT, CAP_STAKE_FX_TARGET, UNSTAKE_FX_TARGET); + } + + function rewardToken() public view returns (address) { + return IRewardDistributor(distributor).rewardToken(); + } + + function claimable(address account) public view returns (uint256) { + UserInfo memory user = userInfo[account]; + uint256 stakedAmount = balanceOf(account); + if (stakedAmount == 0) { + return user.claimableReward; + } + uint256 supply = totalSupply(); + uint256 pendingRewards = IRewardDistributor(distributor).pendingRewards() * (PRECISION); + uint256 nextCumulativeRewardPerToken = vaultInfo.cumulativeRewardPerToken + (pendingRewards / (supply)); + return user.claimableReward + ( + stakedAmount * (nextCumulativeRewardPerToken - (user.previousCumulatedRewardPerToken)) / (PRECISION)); + } + + /**************************************** Only Governor Functions ****************************************/ + + function redelegateValidator( + uint256 srcId, + uint256 dstId, + uint256 redelegateAmount + ) external onlyRole(GOVERNOR_ROLE) { + require(srcId < vaultInfo.length && dstId < vaultInfo.length, "Invalid ID"); + ValInfo memory srcVal = valInfo[srcId]; + ValInfo memory dstVal = valInfo[dstId]; + (, uint256 delegationAmount) = _delegation(srcVal.validator, address(this)); + require(redelegateAmount <= delegationAmount, "!Amount"); + + _compound(); + _redelegateV2(srcVal.validator, dstVal.validator, redelegateAmount); + + emit ValidatorRedelegated(srcVal.validator, dstVal.validator, redelegateAmount, redelegateAmount); + } + + function addValidator( + string memory _validator, + uint256 _allocPoint + ) external onlyRole(GOVERNOR_ROLE) { + require(addedValidator[_validator] == false, "addedVal"); + valInfo[vaultInfo.length].validator = _validator; + valInfo[vaultInfo.length].allocPoint = _allocPoint; + + vaultInfo.length++; + vaultInfo.totalAllocPoint += _allocPoint; + + addedValidator[_validator]=true; + + emit ValidatorAdded(_validator, _allocPoint); + } + + /** + * @notice remove validators which has 0 allocPoint and 0 delegation in the list + */ + function removeValidator() external onlyRole(GOVERNOR_ROLE) { + uint256 valLength = getValLength(); + + for (uint256 i = 0; i < valLength;) { + if (valInfo[i].allocPoint == 0) { + string memory val = valInfo[i].validator; + (uint256 sharesAmount, ) = _delegation(val, address(this)); + + if (sharesAmount == 0) { + addedValidator[val] = false; + uint256 lastIndex = valLength - 1; + valInfo[i] = valInfo[lastIndex]; + delete valInfo[lastIndex]; + + emit ValidatorRemoved(val); + valLength--; + // Skip if i == 0 to prevent underflow + if (i == 0) { + continue; + } else { + --i; + } + } + } + unchecked { + ++i; + } + } + // Reset stakeID, unstakeID, validator length + vaultInfo.stakeId = 0; + vaultInfo.unstakeId = 0; + vaultInfo.length = valLength; + } + + function updateValidator( + uint256 id, + uint256 newAllocPoint + ) external onlyRole(GOVERNOR_ROLE) { + require(id < vaultInfo.length, "Invalid ID"); + uint256 oldAllocPoint = valInfo[id].allocPoint; + + vaultInfo.totalAllocPoint = vaultInfo.totalAllocPoint + newAllocPoint - oldAllocPoint; + valInfo[id].allocPoint = newAllocPoint; + + emit ValidatorUpdated(valInfo[id].validator, newAllocPoint); + } + + /** + * @notice Update vault config(remove STAKE_FX_TARGET) + */ + function updateConfigs(uint256 newMinCompound, uint256 newCapStakeFxTarget, uint256 newUnstakeFxTarget) external onlyRole(GOVERNOR_ROLE) { + MIN_COMPOUND_AMOUNT = newMinCompound; + CAP_STAKE_FX_TARGET = newCapStakeFxTarget; + UNSTAKE_FX_TARGET = newUnstakeFxTarget; + } + + /** + * @notice Update compounding fee percentage for protocol and compounder and user withdrawal percentage + * require(newFeeOnReward + newFeeOnCompounder) <= BIPS_DIVISOR && newFeeOnWithdrawal <= BIPS_DIVISOR) + */ + function updateFees(uint256 newFeeOnReward, uint256 newFeeOnCompounder, uint256 newFeeOnWithdrawal) external onlyRole(GOVERNOR_ROLE) { + feeOnReward = newFeeOnReward; + feeOnCompounder = newFeeOnCompounder; + feeOnWithdrawal = newFeeOnWithdrawal; + } + + /**************************************** Only Owner Functions ****************************************/ + + function updateVestedFX(address newAddress) external onlyRole(OWNER_ROLE) { + vestedFX = newAddress; + emit VestedFXChanged(newAddress); + } + + function updateFeeTreasury(address newAddress) external onlyRole(OWNER_ROLE) { + feeTreasury = newAddress; + emit FeeTreasuryChanged(newAddress); + } + + function updateDistributor(address newAddress) external onlyRole(OWNER_ROLE) { + distributor = newAddress; + emit DistributorChanged(newAddress); + } + + function recoverToken( + address token, + uint256 amount, + address _recipient + ) external onlyRole(OWNER_ROLE) { + require(_recipient != address(0), "Send to zero address"); + if(token != address(0)) { + IERC20Upgradeable(token).safeTransfer(_recipient, amount); + } else { + address recipient = payable(_recipient); + (bool success, ) = recipient.call{value: amount}(""); + require(success, "Failed to send FX"); + } + } + + /************************************************************** + * @dev Initialize the states + *************************************************************/ + + function initialize( + address _asset, + address _owner, + address _governor + ) public initializer { + __BaseVaultInit( + _asset, + "Staked FX Token", + "StFX", + _owner, + _governor + ); + // __Governable_init(_owner, _governor); redundant code + __UUPSUpgradeable_init(); + } +} \ No newline at end of file diff --git a/contracts/VestedFXOld.sol b/contracts/VestedFXOld.sol deleted file mode 100644 index 4f7e2de..0000000 --- a/contracts/VestedFXOld.sol +++ /dev/null @@ -1,280 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.18; - -import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -import {IVestedFX} from "./interfaces/IVestedFX.sol"; // Only for testnet to migrate data from old contract,it will be removed in mainnet -import {IStakeFXVault} from "./interfaces/IStakeFXVault.sol"; - -contract VestedFXOld is Initializable, UUPSUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable { - - using SafeERC20Upgradeable for IERC20Upgradeable; - address private stakeFXVault; - address private fxFeeTreasury; - - struct VestingSchedule { - uint64 startTime; - uint64 endTime; - uint256 quantity; - uint256 vestedQuantity; - } - - /// @dev vesting schedule of an account - mapping(address => VestingSchedule[]) private accountVestingSchedules; - - /// @dev An account's total escrowed balance per token to save recomputing this for fee extraction purposes - mapping(address => uint256) public accountEscrowedBalance; - - /// @dev An account's total vested swap per token - mapping(address => uint256) public accountVestedBalance; - - /* ========== EVENTS ========== */ - event VestingEntryCreated(address indexed beneficiary, uint256 startTime, uint256 endTime, uint256 quantity); - event Vested(address indexed beneficiary, uint256 vestedQuantity, uint256 index); - - receive() external payable {} - - /* ========== MODIFIERS ========== */ - modifier onlyStakeFX() { - require(msg.sender == (stakeFXVault), "Only stakeFX can call"); - _; - } - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - /****************************************** Core Functions ******************************************/ - /** - * @dev Allow a user to vest all ended schedules - */ - function vestCompletedSchedules() public nonReentrant returns (uint256) { - uint256 totalVesting = 0; - totalVesting = _vestCompletedSchedules(); - - return totalVesting; - } - - /**************************************** View Functions ****************************************/ - /** - * @notice The number of vesting dates in an account's schedule. - */ - function numVestingSchedules(address account) external view returns (uint256) { - return accountVestingSchedules[account].length; - } - - /** - * @dev manually get vesting schedule at index - */ - function getVestingScheduleAtIndex(address account, uint256 index) external view returns (VestingSchedule memory) { - return accountVestingSchedules[account][index]; - } - - /** - * @dev Get all schedules for an account. - */ - function getVestingSchedules(address account) external view returns (VestingSchedule[] memory) { - return accountVestingSchedules[account]; - } - - function getstakeFXVault() external view returns (address) { - return address(stakeFXVault); - } - - function getFxFeeTreasury() external view returns (address) { - return address(fxFeeTreasury); - } - - /* ==================== INTERNAL FUNCTIONS ==================== */ - /** - * @dev Allow a user to vest all ended schedules - */ - function _vestCompletedSchedules() internal returns (uint256) { - VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender]; - uint256 schedulesLength = schedules.length; - - uint256 totalVesting = 0; - for (uint256 i = 0; i < schedulesLength; i++) { - VestingSchedule memory schedule = schedules[i]; - if (_getBlockTime() < schedule.endTime) { - continue; - } - - uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity); - if (vestQuantity == 0) { - continue; - } - schedules[i].vestedQuantity = schedule.quantity; - totalVesting = totalVesting + (vestQuantity); - - emit Vested(msg.sender, vestQuantity, i); - } - _completeVesting(totalVesting); - _clearClaimedSchedule(); - - return totalVesting; - } - - function _completeVesting(uint256 totalVesting) internal { - require(totalVesting != 0, '0 vesting amount'); - - accountEscrowedBalance[msg.sender] = accountEscrowedBalance[msg.sender] - (totalVesting); - accountVestedBalance[msg.sender] = accountVestedBalance[msg.sender] + (totalVesting); - - uint256 liquidity = (stakeFXVault).balance; - - if(liquidity < totalVesting) { - uint256 feesTreasuryLiquidity = address(fxFeeTreasury).balance; - require((liquidity + feesTreasuryLiquidity) >= totalVesting, "Insuffient liq"); - IStakeFXVault(fxFeeTreasury).sendVestedFX(totalVesting - liquidity); - IStakeFXVault(stakeFXVault).sendVestedFX(liquidity); - } else { - IStakeFXVault(stakeFXVault).sendVestedFX(totalVesting); - } - address recipient = payable(msg.sender); - (bool success, ) = recipient.call{value: totalVesting}(""); - require(success, "Failed to send FX"); - } - - /** - * @dev Delete User claimed schedule - */ - // function _clearClaimedSchedule() internal { - // VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender]; - // uint256 schedulesLength = schedules.length; - - // for (uint256 i = 0; i < schedulesLength; i++) { - // VestingSchedule memory schedule = schedules[i]; - - // uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity); - // if (vestQuantity == 0) { - // continue; - // } else { - // uint256 index = i; - // for(uint256 i = 0; i < schedules.length-index; i++) { - // schedules[i] = schedules[i+index]; - // } - // for(uint256 i = 0; i < index; i++) { - // schedules.pop(); - // } - // break; - // } - // } - // } - function _clearClaimedSchedule() internal { - VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender]; - uint256 schedulesLength = schedules.length; - uint256 index; - for (index = 0; index < schedulesLength; index++) { - VestingSchedule memory schedule = schedules[index]; - - uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity); - if (vestQuantity == 0) { - continue; - } else { - break; - } - } - - if (index !=0) { - for(uint256 i = 0; i < schedules.length-index; i++) { - schedules[i] = schedules[i+index]; - } - for(uint256 i = 0; i < index; i++) { - schedules.pop(); - } - } - } - - /** - * @dev wrap block.timestamp so we can easily mock it - */ - function _getBlockTime() internal virtual view returns (uint32) { - return uint32(block.timestamp); - } - - /**************************************** Only Authorised Functions ****************************************/ - - function lockWithEndTime(address account, uint256 quantity, uint256 endTime) external onlyStakeFX { - require(quantity > 0, '0 quantity'); - - VestingSchedule[] storage schedules = accountVestingSchedules[account]; - - // append new schedule - schedules.push(VestingSchedule({ - startTime: uint64(block.timestamp), - endTime: uint64(endTime), - quantity: quantity, - vestedQuantity: 0 - })); - - // record total vesting balance of user - accountEscrowedBalance[account] = accountEscrowedBalance[account] + (quantity); - - emit VestingEntryCreated(account, block.timestamp, endTime, quantity); - } - - /** - * @dev Only for testnet to migrate data from old contract,it will be removed in mainnet - */ - function migrateData(address account) external onlyOwner { - require(account != address(0), '0 quantity'); - address oldVestedFX = 0xEe541f260C9fa4bFED73fF97C1dfB0483A684259; - VestingSchedule[] storage schedules = accountVestingSchedules[account]; - IVestedFX.VestingSchedule[] memory oldSchedules; - - oldSchedules = IVestedFX(oldVestedFX).getVestingSchedules(account); - uint256 oldAccountEscrowedBalance = IVestedFX(oldVestedFX).accountEscrowedBalance(account); - uint256 oldAccountVestedBalance = IVestedFX(oldVestedFX).accountVestedBalance(account); - - // append new schedule - for (uint256 i = 0; i < oldSchedules.length; i++) { - schedules.push( - VestingSchedule({ - startTime: uint64(oldSchedules[i].startTime), - endTime: uint64(oldSchedules[i].endTime), - quantity: oldSchedules[i].quantity, - vestedQuantity: oldSchedules[i].vestedQuantity - }) - ); - } - - // record total vesting balance of user - accountEscrowedBalance[account] = oldAccountEscrowedBalance; - accountVestedBalance[account] = oldAccountVestedBalance; - } - - function recoverToken(address token, uint256 amount, address recipient) external onlyOwner nonReentrant{ - require(recipient != address(0), "Send to zero address"); - IERC20Upgradeable(token).safeTransfer(recipient, amount); - } - - function updateStakeFXVault(address _stakeFXVault) external onlyOwner nonReentrant{ - stakeFXVault = _stakeFXVault; - } - - function updateFxFeeTreasury(address _fxFeeTreasury) external onlyOwner { - fxFeeTreasury = _fxFeeTreasury; - } - - function _authorizeUpgrade(address) internal override onlyOwner {} - - /************************************************************** - * @dev Initialize the states - *************************************************************/ - - function initialize(address _stakeFXVault, address _fxFeeTreasury) public initializer { - stakeFXVault = _stakeFXVault; - fxFeeTreasury = _fxFeeTreasury; - - __Ownable_init(); - __UUPSUpgradeable_init(); - } -} \ No newline at end of file diff --git a/contracts/Vester.sol b/contracts/Vester.sol new file mode 100644 index 0000000..2cd5968 --- /dev/null +++ b/contracts/Vester.sol @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.18; + +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + +import {Governable} from "./common/Governable.sol"; +import "./interfaces/IMintable.sol"; + +contract Vester is IERC20, Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable, Governable { + using SafeERC20 for IERC20; + + string public name; + string public symbol; + uint8 public constant decimals = 18; + + uint256 public vestingDuration; + + address public esToken; + address public claimableToken; + + uint256 public override totalSupply; + + mapping (address => uint256) public balances; + mapping (address => uint256) public cumulativeClaimAmounts; + mapping (address => uint256) public claimedAmounts; + mapping (address => uint256) public lastVestingTimes; + + mapping (address => bool) public isHandler; + + event Claim(address receiver, uint256 amount); + event Deposit(address account, uint256 amount); + event Withdraw(address account, uint256 claimedAmount, uint256 balance); + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + + /************************************************************** + * Core user functions + *************************************************************/ + + function deposit(uint256 _amount) external nonReentrant { + _deposit(msg.sender, _amount); + } + + function depositForAccount(address _account, uint256 _amount) external nonReentrant { + _validateHandler(); + _deposit(_account, _amount); + } + + function withdraw() external nonReentrant { + address account = msg.sender; + address _receiver = account; + _claim(account, _receiver); + + uint256 claimedAmount = cumulativeClaimAmounts[account]; + uint256 balance = balances[account]; + uint256 totalVested = balance + (claimedAmount); + require(totalVested > 0, "Vester: vested amount is zero"); + + IERC20(esToken).safeTransfer(_receiver, balance); + _burn(account, balance); + + delete cumulativeClaimAmounts[account]; + delete claimedAmounts[account]; + delete lastVestingTimes[account]; + + emit Withdraw(account, claimedAmount, balance); + } + + function claim() external nonReentrant returns (uint256) { + return _claim(msg.sender, msg.sender); + } + + function claimForAccount(address _account, address _receiver) external nonReentrant returns (uint256) { + _validateHandler(); + return _claim(_account, _receiver); + } + + /************************************************************** + * View functions + *************************************************************/ + + function claimable(address _account) public view returns (uint256) { + uint256 amount = cumulativeClaimAmounts[_account] - (claimedAmounts[_account]); + uint256 nextClaimable = _getNextClaimableAmount(_account); + return amount + (nextClaimable); + } + + function getTotalVested(address _account) public view returns (uint256) { + return balances[_account] + (cumulativeClaimAmounts[_account]); + } + + function balanceOf(address _account) public view override returns (uint256) { + return balances[_account]; + } + + function getVestedAmount(address _account) public view returns (uint256) { + uint256 balance = balances[_account]; + uint256 cumulativeClaimAmount = cumulativeClaimAmounts[_account]; + return balance + (cumulativeClaimAmount); + } + + /************************************************************** + * Internal functions + *************************************************************/ + + function _mint(address _account, uint256 _amount) private { + require(_account != address(0), "Vester: mint to the zero address"); + + totalSupply = totalSupply + (_amount); + balances[_account] = balances[_account] + (_amount); + + emit Transfer(address(0), _account, _amount); + } + + function _burn(address _account, uint256 _amount) private { + require(_account != address(0), "Vester: burn from the zero address"); + + balances[_account] = balances[_account] - (_amount); // "Vester: burn amount exceeds balance" + totalSupply = totalSupply - (_amount); + + emit Transfer(_account, address(0), _amount); + } + + function _deposit(address _account, uint256 _amount) private { + require(_amount > 0, "Vester: invalid _amount"); + + _claim(_account, _account); + + IERC20(esToken).safeTransferFrom(_account, address(this), _amount); + + _mint(_account, _amount); + + emit Deposit(_account, _amount); + } + + function _claim(address _account, address _receiver) private returns (uint256) { + _updateVesting(_account); + uint256 amount = claimable(_account); + claimedAmounts[_account] = claimedAmounts[_account] + (amount); + IERC20(claimableToken).safeTransfer(_receiver, amount); + emit Claim(_account, amount); + return amount; + } + + function _updateVesting(address _account) private { + uint256 amount = _getNextClaimableAmount(_account); + lastVestingTimes[_account] = block.timestamp; + + if (amount == 0) { + return; + } + + // transfer claimableAmount from balances to cumulativeClaimAmounts + _burn(_account, amount); + cumulativeClaimAmounts[_account] = cumulativeClaimAmounts[_account] + (amount); + + IMintable(esToken).burn(amount); + } + + function _getNextClaimableAmount(address _account) internal view returns (uint256) { + uint256 balance = balances[_account]; + if (balance == 0) { return 0; } + + uint256 timeDiff = block.timestamp - (lastVestingTimes[_account]); + + uint256 vestedAmount = getVestedAmount(_account); + uint256 claimableAmount = vestedAmount * (timeDiff) / (vestingDuration); + + if (claimableAmount < balance) { + return claimableAmount; + } + + return balance; + } + + function _validateHandler() private view { + require(isHandler[msg.sender], "Vester: forbidden"); + } + + /************************************************************** + * Empty ERC20 implementation functions + *************************************************************/ + + // empty implementation, tokens are non-transferrable + function transfer(address /* recipient */, uint256 /* amount */) public override returns (bool) { + revert("Vester: non-transferrable"); + } + + // empty implementation, tokens are non-transferrable + function allowance(address /* owner */, address /* spender */) public view virtual override returns (uint256) { + return 0; + } + + // empty implementation, tokens are non-transferrable + function approve(address /* spender */, uint256 /* amount */) public virtual override returns (bool) { + revert("Vester: non-transferrable"); + } + + // empty implementation, tokens are non-transferrable + function transferFrom(address /* sender */, address /* recipient */, uint256 /* amount */) public virtual override returns (bool) { + revert("Vester: non-transferrable"); + } + + /************************************************************** + * Only Owner functions + *************************************************************/ + function _authorizeUpgrade(address) internal override onlyRole(OWNER_ROLE) {} + + // to help users who accidentally send their tokens to this contract + function recoverToken(address _token, address _account, uint256 _amount) external onlyRole(OWNER_ROLE) { + IERC20(_token).safeTransfer(_account, _amount); + } + + function setHandler(address _handler, bool _isActive) external onlyRole(OWNER_ROLE) { + isHandler[_handler] = _isActive; + } + + function mintEsToken(uint256 _amount) external nonReentrant onlyRole(OWNER_ROLE){ + IERC20(claimableToken).transferFrom(msg.sender, address(this), _amount); + IMintable(esToken).mint(msg.sender, _amount); + } + + /************************************************************** + * @dev Initialize smart contract functions - only called once + *************************************************************/ + function initialize( + string memory _name, + string memory _symbol, + uint256 _vestingDuration, + address _esToken, + address _claimableToken, + address _owner, + address _governor + ) public initializer{ + name = _name; + symbol = _symbol; + + vestingDuration = _vestingDuration; + + esToken = _esToken; + claimableToken = _claimableToken; + __Governable_init(_owner, _governor); + __UUPSUpgradeable_init(); + } +} \ No newline at end of file diff --git a/contracts/attackContract.sol b/contracts/attackContract.sol deleted file mode 100644 index 25d7f41..0000000 --- a/contracts/attackContract.sol +++ /dev/null @@ -1,202 +0,0 @@ -pragma solidity ^0.8.18; - -library Encode { - function delegate( - string memory _validator - ) internal pure returns (bytes memory) { - return abi.encodeWithSignature("delegate(string)", _validator); - } - - function undelegate( - string memory _validator, - uint256 _shares - ) internal pure returns (bytes memory) { - return abi.encodeWithSignature("undelegate(string,uint256)", _validator, _shares); - } - - function withdraw( - string memory _validator - ) internal pure returns (bytes memory) { - return abi.encodeWithSignature("withdraw(string)", _validator); - } - - function transferFromShares( - string memory _validator, - address _from, - address _to, - uint256 _shares - ) internal pure returns (bytes memory) { - return abi.encodeWithSignature("transferFromShares(string,address,address,uint256)", _validator, _from, _to, _shares); - } - - function delegation( - string memory _validator, - address _delegate - ) internal pure returns (bytes memory) { - return abi.encodeWithSignature("delegation(string,address)", _validator, _delegate); - } - - function delegationRewards( - string memory _validator, - address _delegate) internal pure returns (bytes memory) { - return abi.encodeWithSignature("delegationRewards(string,address)", _validator, _delegate); - } -} - -pragma solidity ^0.8.18; - -library Decode { - function delegate( - bytes memory data - ) internal pure returns (uint256, uint256) { - (uint256 shares, uint256 reward) = abi.decode(data, (uint256, uint256)); - return (shares, reward); - } - - function undelegate( - bytes memory data - ) internal pure returns (uint256, uint256, uint256) { - (uint256 amount, uint256 reward, uint256 endTime) = abi.decode( - data, - (uint256, uint256, uint256) - ); - return (amount, reward, endTime); - } - - function withdraw(bytes memory data) internal pure returns (uint256) { - uint256 reward = abi.decode(data, (uint256)); - return reward; - } - - function transferFromShares(bytes memory data) internal pure returns (uint256, uint256) { - (uint256 token, uint256 reward) = abi.decode(data, (uint256, uint256)); - return (token, reward); - } - - function delegation(bytes memory data) internal pure returns (uint256, uint256) { - (uint256 delegateShare, uint256 delegateAmount) = abi.decode(data, (uint256, uint256)); - return (delegateShare, delegateAmount); - } - - function delegationRewards(bytes memory data) internal pure returns (uint256) { - uint256 rewardAmount= abi.decode(data, (uint256)); - return rewardAmount; - } - - function ok( - bool _result, - bytes memory _data, - string memory _msg - ) internal pure { - if (!_result) { - string memory errMsg = abi.decode(_data, (string)); - if (bytes(_msg).length < 1) { - revert(errMsg); - } - revert(string(abi.encodePacked(_msg, ": ", errMsg))); - } - } -} - -abstract contract PrecompileStaking { - - address private constant _stakingAddress = address(0x0000000000000000000000000000000000001003); - - /**************************************** Precompile Staking Internal Functions ****************************************/ - - function _delegate(string memory _val, uint256 _amount) internal returns (uint256, uint256) { - (bool result, bytes memory data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val)); - Decode.ok(result, data, "delegate failed"); - - return Decode.delegate(data); - } - - function _undelegate(string memory _val, uint256 _shares) internal returns (uint256, uint256, uint256) { - (bool result, bytes memory data) = _stakingAddress.call(Encode.undelegate(_val, _shares)); - Decode.ok(result, data, "undelegate failed"); - - return Decode.undelegate(data); - } - - function _withdraw(string memory _val) internal returns (uint256) { - (bool result, bytes memory data) = _stakingAddress.call(Encode.withdraw(_val)); - Decode.ok(result, data, "withdraw failed"); - - return Decode.withdraw(data); - } - - function _transferFromShares(string memory _val, address _from, address _to, uint256 _shares) internal returns (uint256, uint256) { - (bool result, bytes memory data) = _stakingAddress.call(Encode.transferFromShares(_val, _from, _to, _shares)); - Decode.ok(result, data, "transferFromShares failed"); - - return Decode.transferFromShares(data); - } - - function _delegation(string memory _val, address _del) internal view returns (uint256, uint256) { - (bool result, bytes memory data) = _stakingAddress.staticcall(Encode.delegation(_val, _del)); - Decode.ok(result, data, "delegation failed"); - - return Decode.delegation(data); - } - - function _delegationRewards(string memory _val, address _del) internal view returns (uint256) { - (bool result, bytes memory data) = _stakingAddress.staticcall(Encode.delegationRewards(_val, _del)); - Decode.ok(result, data, "delegationRewards failed"); - - return Decode.delegationRewards(data); - } -} - -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -/** - * @title Ballot - * @dev Implements voting process along with vote delegation - */ -contract test is PrecompileStaking{ - - string private val = "fxvaloper1t67ryvnqmnud5g3vpmck00l3umelwkz7huh0s3"; - string private val1 = "fxvaloper1etzrlsszsm0jaj4dp5l25vk3p4w0x4ntl64hlw"; - - function stake(uint256 index) external payable { - _stake(index); - } - - function _stake(uint256 index) internal { - uint256 amount = 100000000000000000000; - for (uint256 i =0; i< index; i++) { - _delegate(val, amount); - } - } - - function stake1(uint256 index) external payable { - _stake1(index); - } - - function _stake1(uint256 index) internal { - uint256 amount = 100000000000000000000; - for (uint256 i =0; i< index; i++) { - _delegate(val, amount); - _delegate(val1, amount); - } - } - - function getDelegationInfo() external view returns (uint256, uint256) { - (uint256 sharesAmount, uint256 delegationAmount) = _delegation(val, address(this)); - return (sharesAmount, delegationAmount); - } - - function getDelegationInfo1() external view returns (uint256, uint256) { - (uint256 sharesAmount, uint256 delegationAmount) = _delegation(val1, address(this)); - return (sharesAmount, delegationAmount); - } -} - -interface test2 { - function stake() external payable; - - function totalAssets() external view returns(uint256); - -} \ No newline at end of file diff --git a/contracts/common/Governable.sol b/contracts/common/Governable.sol index c0407bb..b2d4702 100644 --- a/contracts/common/Governable.sol +++ b/contracts/common/Governable.sol @@ -24,5 +24,5 @@ abstract contract Governable is AccessControlUpgradeable { * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[49] private __gap; + // uint256[49] private __gap; } \ No newline at end of file diff --git a/contracts/imp/PrecompileStaking.sol b/contracts/imp/PrecompileStaking.sol index a7a4d52..f0ab9f5 100644 --- a/contracts/imp/PrecompileStaking.sol +++ b/contracts/imp/PrecompileStaking.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.10; import {Encode} from "../libraries/Encode.sol"; import {Decode} from "../libraries/Decode.sol"; +import {IPrecompileStaking} from "../interfaces/IPrecompileStaking.sol"; /** * @title PrecompileStaking @@ -30,6 +31,26 @@ abstract contract PrecompileStaking { return Decode.undelegate(data); } + function _redelegate(string memory _valSrc, string memory _valDst, uint256 _shares) internal returns (uint256, uint256, uint256) { + (bool result, bytes memory data) = _stakingAddress.call(Encode.redelegate(_valSrc, _valDst, _shares)); + Decode.ok(result, data, "redelegate failed"); + + return Decode.redelegate(data); + } + + function _delegateV2(string memory _val, uint256 _amount) internal returns (bool _result) { + require(address(this).balance >= _amount, "insufficient balance"); + return IPrecompileStaking(_stakingAddress).delegateV2(_val, _amount); + } + + function _undelegateV2(string memory _val, uint256 _amount) internal returns (bool _result) { + return IPrecompileStaking(_stakingAddress).undelegateV2(_val,_amount); + } + + function _redelegateV2(string memory _valSrc, string memory _valDst, uint256 _amount) internal returns (bool _result) { + return IPrecompileStaking(_stakingAddress).redelegateV2(_valSrc, _valDst, _amount); + } + function _withdraw(string memory _val) internal returns (uint256) { (bool result, bytes memory data) = _stakingAddress.call(Encode.withdraw(_val)); Decode.ok(result, data, "withdraw failed"); @@ -37,6 +58,13 @@ abstract contract PrecompileStaking { return Decode.withdraw(data); } + function _transferShares(string memory _val, address _to, uint256 _shares) internal returns (uint256, uint256) { + (bool result, bytes memory data) = _stakingAddress.call(Encode.transferShares(_val, _to, _shares)); + Decode.ok(result, data, "transferShares failed"); + + return Decode.transferShares(data); + } + function _transferFromShares(string memory _val, address _from, address _to, uint256 _shares) internal returns (uint256, uint256) { (bool result, bytes memory data) = _stakingAddress.call(Encode.transferFromShares(_val, _from, _to, _shares)); Decode.ok(result, data, "transferFromShares failed"); @@ -58,10 +86,17 @@ abstract contract PrecompileStaking { return Decode.delegationRewards(data); } + function _allowanceShares(string memory _val, address _owner, address _spender) internal view returns (uint256) { + (bool result, bytes memory data) = _stakingAddress.staticcall(Encode.allowanceShares(_val, _owner, _spender)); + Decode.ok(result, data, "allowanceShares failed"); + + return Decode.allowanceShares(data); + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[49] private __gap; + // uint256[49] private __gap; } \ No newline at end of file diff --git a/contracts/interfaces/IMintable.sol b/contracts/interfaces/IMintable.sol new file mode 100644 index 0000000..41d653a --- /dev/null +++ b/contracts/interfaces/IMintable.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.18; + +interface IMintable { + function mint(address _account, uint256 _amount) external; + + function burn(uint256 _amount) external; +} \ No newline at end of file diff --git a/contracts/interfaces/IPrecompileStaking.sol b/contracts/interfaces/IPrecompileStaking.sol index a439ffc..bc136dc 100644 --- a/contracts/interfaces/IPrecompileStaking.sol +++ b/contracts/interfaces/IPrecompileStaking.sol @@ -21,4 +21,19 @@ interface IPrecompileStaking { function delegationRewards(string memory _val, address _del) external view returns (uint256); + function delegateV2( + string memory _val, + uint256 _amount + ) external payable returns (bool _result); + + function undelegateV2( + string memory _val, + uint256 _amount + ) external returns (bool _result); + + function redelegateV2( + string memory _valSrc, + string memory _valDst, + uint256 _amount + ) external returns (bool _result); } \ No newline at end of file diff --git a/contracts/interfaces/IStakeFXVault.sol b/contracts/interfaces/IStakeFXVault.sol index 68f2876..634983f 100644 --- a/contracts/interfaces/IStakeFXVault.sol +++ b/contracts/interfaces/IStakeFXVault.sol @@ -11,4 +11,14 @@ interface IStakeFXVault { function getValLength() external view returns (uint256); function getValInfo(uint256 index) external view returns (uint256, string memory); + + function stake(uint256 amount, bool native) external payable; + + function unstake(uint256 amount) external; + + function entrustDelegatedShare(string memory val, uint256 amount) external; + + function compound() external; + + function claim(address receiver) external returns (uint256); } diff --git a/contracts/libraries/Decode.sol b/contracts/libraries/Decode.sol index d11077a..f424bce 100644 --- a/contracts/libraries/Decode.sol +++ b/contracts/libraries/Decode.sol @@ -20,11 +20,43 @@ library Decode { return (amount, reward, endTime); } + function redelegate(bytes memory data) internal pure returns (uint256, uint256, uint256) { + (uint256 _amount, uint256 _reward, uint256 _completionTime) = abi.decode(data, (uint256, uint256, uint256)); + return (_amount, _reward, _completionTime); + } + + function delegateV2( + bytes memory data + ) internal pure returns (bool) { + (bool _result) = abi.decode(data, (bool)); + return (_result); + } + + function undelegateV2( + bytes memory data + ) internal pure returns (bool) { + (bool _result) = abi.decode( + data, + (bool) + ); + return (_result); + } + + function redelegateV2(bytes memory data) internal pure returns (bool) { + (bool _result) = abi.decode(data, (bool)); + return (_result); + } + function withdraw(bytes memory data) internal pure returns (uint256) { uint256 reward = abi.decode(data, (uint256)); return reward; } + function transferShares(bytes memory data) internal pure returns (uint256, uint256) { + (uint256 token, uint256 reward) = abi.decode(data, (uint256, uint256)); + return (token, reward); + } + function transferFromShares(bytes memory data) internal pure returns (uint256, uint256) { (uint256 token, uint256 reward) = abi.decode(data, (uint256, uint256)); return (token, reward); @@ -36,10 +68,15 @@ library Decode { } function delegationRewards(bytes memory data) internal pure returns (uint256) { - uint256 rewardAmount= abi.decode(data, (uint256)); + uint256 rewardAmount = abi.decode(data, (uint256)); return rewardAmount; } + function allowanceShares(bytes memory data) internal pure returns (uint256) { + uint256 allowanceAmount = abi.decode(data, (uint256)); + return allowanceAmount; + } + function ok( bool _result, bytes memory _data, diff --git a/contracts/libraries/Encode.sol b/contracts/libraries/Encode.sol index ef9cf54..fd7ed7b 100644 --- a/contracts/libraries/Encode.sol +++ b/contracts/libraries/Encode.sol @@ -16,12 +16,50 @@ library Encode { return abi.encodeWithSignature("undelegate(string,uint256)", _validator, _shares); } + function redelegate( + string memory _valSrc, + string memory _valDst, + uint256 _shares + ) internal pure returns (bytes memory) { + return abi.encodeWithSignature("redelegate(string,string,uint256)", _valSrc, _valDst, _shares); + } + + function delegateV2( + string memory _validator, + uint256 _amount + ) internal pure returns (bytes memory) { + return abi.encodeWithSignature("delegate(string, uint256)", _validator, _amount); + } + + function undelegateV2( + string memory _validator, + uint256 _amount + ) internal pure returns (bytes memory) { + return abi.encodeWithSignature("undelegate(string,uint256)", _validator, _amount); + } + + function redelegateV2( + string memory _valSrc, + string memory _valDst, + uint256 _amount + ) internal pure returns (bytes memory) { + return abi.encodeWithSignature("redelegate(string,string,uint256)", _valSrc, _valDst, _amount); + } + function withdraw( string memory _validator ) internal pure returns (bytes memory) { return abi.encodeWithSignature("withdraw(string)", _validator); } + function transferShares( + string memory _validator, + address _to, + uint256 _shares + ) internal pure returns (bytes memory) { + return abi.encodeWithSignature("transferFromShares(string,address,uint256)", _validator, _to, _shares); + } + function transferFromShares( string memory _validator, address _from, @@ -43,4 +81,11 @@ library Encode { address _delegate) internal pure returns (bytes memory) { return abi.encodeWithSignature("delegationRewards(string,address)", _validator, _delegate); } + + function allowanceShares( + string memory _validator, + address _owner, + address _spender) internal pure returns (bytes memory) { + return abi.encodeWithSignature("allowanceShares(string,address,address)", _validator, _owner, _spender); + } } diff --git a/contracts/vaults/BaseVault.sol b/contracts/vaults/BaseVault.sol index 84361c7..b2f86b3 100644 --- a/contracts/vaults/BaseVault.sol +++ b/contracts/vaults/BaseVault.sol @@ -131,5 +131,5 @@ abstract contract BaseVault is Governable, PausableUpgradeable, ERC4626Upgradeab * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[49] private __gap; + // uint256[49] private __gap; } \ No newline at end of file diff --git a/hardhat.config.js b/hardhat.config.js index 5c33fb9..aa8d602 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -16,6 +16,7 @@ const TESTNET_PRIVATE_KEY = fs.readFileSync(".secret").toString().trim(); module.exports = { solidity: { version: "0.8.18", + settings: { optimizer: { enabled: true, @@ -62,6 +63,14 @@ module.exports = { gas: 12400000, gasPrice: 600000000000, }, + local: { + url: `http://192.168.1.115:8545`, + accounts: [TESTNET_PRIVATE_KEY], + networkCheckTimeout: 999999, + timeoutBlocks: 200, + gas: 12400000, + gasPrice: 600000000000, + }, fxMainnet: { url: `https://fx-json-web3.functionx.io:8545`, accounts: [MAINNET_PRIVATE_KEY], diff --git a/out/linecounter.json b/out/linecounter.json new file mode 100644 index 0000000..e6a17ae --- /dev/null +++ b/out/linecounter.json @@ -0,0 +1,1641 @@ +{ + "extension": "linecounter", + "version": "0.2.7", + "workspace": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound", + "linecount": [ + { + "version": "0.2.7", + "counttime": "2023-09-06 10:59:15", + "filesum": 131, + "codesum": 120582, + "commentsum": 423, + "blanksum": 2302, + "statistics": { + ".js": { + "code": 222, + "comment": 125, + "blank": 94 + }, + "": { + "code": 11, + "comment": 0, + "blank": 0 + }, + ".json": { + "code": 118912, + "comment": 0, + "blank": 1794 + }, + ".md": { + "code": 10, + "comment": 0, + "blank": 3 + }, + ".sol": { + "code": 1427, + "comment": 298, + "blank": 411 + } + }, + "filelist": [ + { + "blank": 0, + "code": 11, + "comment": 0, + "filename": ".gitignore" + }, + { + "blank": 0, + "code": 1795, + "comment": 0, + "filename": ".openzeppelin/unknown-530.json" + }, + { + "blank": 0, + "code": 6210, + "comment": 0, + "filename": ".openzeppelin/unknown-90001.json" + }, + { + "blank": 0, + "code": 0, + "comment": 0, + "filename": ".secret" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 228, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 183, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 76, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 56, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 623, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 69, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 113, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 63, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 294, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 684, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 233, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 86, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 194, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 43, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 30, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/0741eeb9b315cb9b0ec518d0b68d9782.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/2d5bbffb16669edfd417b27cee834037.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/812966bfa960758020392658194fda8b.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/d5b668fee5834f9f49f46dc9b302ec28.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Decode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Decode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Encode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Encode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/PrecompileStaking.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/PrecompileStaking.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test.dbg.json" + }, + { + "blank": 0, + "code": 73, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test2.dbg.json" + }, + { + "blank": 0, + "code": 31, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test2.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/common/Governable.sol/Governable.dbg.json" + }, + { + "blank": 0, + "code": 267, + "comment": 0, + "filename": "artifacts/contracts/common/Governable.sol/Governable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/FeeTreasury.sol/FeeTreasury.dbg.json" + }, + { + "blank": 0, + "code": 293, + "comment": 0, + "filename": "artifacts/contracts/FeeTreasury.sol/FeeTreasury.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.dbg.json" + }, + { + "blank": 0, + "code": 180, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.dbg.json" + }, + { + "blank": 0, + "code": 63, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.dbg.json" + }, + { + "blank": 0, + "code": 68, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.dbg.json" + }, + { + "blank": 0, + "code": 113, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IWFX.sol/IWFX.dbg.json" + }, + { + "blank": 0, + "code": 59, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IWFX.sol/IWFX.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/libraries/Decode.sol/Decode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/libraries/Decode.sol/Decode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/libraries/Encode.sol/Encode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/libraries/Encode.sol/Encode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/MultiCall.sol/MultiCall.dbg.json" + }, + { + "blank": 0, + "code": 254, + "comment": 0, + "filename": "artifacts/contracts/MultiCall.sol/MultiCall.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/RewardDistributor.sol/RewardDistributor.dbg.json" + }, + { + "blank": 0, + "code": 536, + "comment": 0, + "filename": "artifacts/contracts/RewardDistributor.sol/RewardDistributor.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/StakeFXVault.sol/StakeFXVault.dbg.json" + }, + { + "blank": 0, + "code": 1875, + "comment": 0, + "filename": "artifacts/contracts/StakeFXVault.sol/StakeFXVault.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/vaults/BaseVault.sol/BaseVault.dbg.json" + }, + { + "blank": 0, + "code": 980, + "comment": 0, + "filename": "artifacts/contracts/vaults/BaseVault.sol/BaseVault.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/VestedFX.sol/VestedFX.dbg.json" + }, + { + "blank": 0, + "code": 503, + "comment": 0, + "filename": "artifacts/contracts/VestedFX.sol/VestedFX.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/VestedFXOld.sol/VestedFXOld.dbg.json" + }, + { + "blank": 0, + "code": 516, + "comment": 0, + "filename": "artifacts/contracts/VestedFXOld.sol/VestedFXOld.json" + }, + { + "blank": 200, + "code": 1516, + "comment": 0, + "filename": "cache/solidity-files-cache.json" + }, + { + "blank": 1568, + "code": 83511, + "comment": 0, + "filename": "cache/validations.json" + }, + { + "blank": 42, + "code": 154, + "comment": 6, + "filename": "contracts/attackContract.sol" + }, + { + "blank": 5, + "code": 15, + "comment": 9, + "filename": "contracts/common/Governable.sol" + }, + { + "blank": 15, + "code": 64, + "comment": 8, + "filename": "contracts/FeeTreasury.sol" + }, + { + "blank": 18, + "code": 37, + "comment": 12, + "filename": "contracts/imp/PrecompileStaking.sol" + }, + { + "blank": 9, + "code": 9, + "comment": 6, + "filename": "contracts/interfaces/IPrecompileStaking.sol" + }, + { + "blank": 2, + "code": 7, + "comment": 1, + "filename": "contracts/interfaces/IRewardDistributor.sol" + }, + { + "blank": 6, + "code": 7, + "comment": 1, + "filename": "contracts/interfaces/IStakeFXVault.sol" + }, + { + "blank": 7, + "code": 13, + "comment": 1, + "filename": "contracts/interfaces/IVestedFX.sol" + }, + { + "blank": 4, + "code": 6, + "comment": 1, + "filename": "contracts/interfaces/IWFX.sol" + }, + { + "blank": 8, + "code": 47, + "comment": 1, + "filename": "contracts/libraries/Decode.sol" + }, + { + "blank": 7, + "code": 38, + "comment": 1, + "filename": "contracts/libraries/Encode.sol" + }, + { + "blank": 16, + "code": 64, + "comment": 11, + "filename": "contracts/MultiCall.sol" + }, + { + "blank": 24, + "code": 69, + "comment": 9, + "filename": "contracts/RewardDistributor.sol" + }, + { + "blank": 131, + "code": 511, + "comment": 91, + "filename": "contracts/StakeFXVault.sol" + }, + { + "blank": 19, + "code": 76, + "comment": 40, + "filename": "contracts/vaults/BaseVault.sol" + }, + { + "blank": 46, + "code": 144, + "comment": 37, + "filename": "contracts/VestedFX.sol" + }, + { + "blank": 52, + "code": 166, + "comment": 63, + "filename": "contracts/VestedFXOld.sol" + }, + { + "blank": 3, + "code": 75, + "comment": 18, + "filename": "hardhat.config.js" + }, + { + "blank": 26, + "code": 16563, + "comment": 0, + "filename": "package-lock.json" + }, + { + "blank": 0, + "code": 22, + "comment": 0, + "filename": "package.json" + }, + { + "blank": 3, + "code": 10, + "comment": 0, + "filename": "README.md" + }, + { + "blank": 38, + "code": 20, + "comment": 76, + "filename": "scripts/deploy.js" + }, + { + "blank": 29, + "code": 89, + "comment": 9, + "filename": "test/Lock.js" + }, + { + "blank": 24, + "code": 38, + "comment": 22, + "filename": "test/test.js" + }, + { + "blank": 0, + "code": 63, + "comment": 0, + "filename": "test/verify.json" + } + ] + }, + { + "version": "0.2.7", + "counttime": "2023-09-06 11:01:23", + "filesum": 129, + "codesum": 120262, + "commentsum": 354, + "blanksum": 2208, + "statistics": { + "": { + "code": 11, + "comment": 0, + "blank": 0 + }, + ".js": { + "code": 222, + "comment": 125, + "blank": 94 + }, + ".md": { + "code": 10, + "comment": 0, + "blank": 3 + }, + ".sol": { + "code": 1107, + "comment": 229, + "blank": 317 + }, + ".json": { + "code": 118912, + "comment": 0, + "blank": 1794 + } + }, + "filelist": [ + { + "blank": 0, + "code": 11, + "comment": 0, + "filename": ".gitignore" + }, + { + "blank": 0, + "code": 1795, + "comment": 0, + "filename": ".openzeppelin/unknown-530.json" + }, + { + "blank": 0, + "code": 6210, + "comment": 0, + "filename": ".openzeppelin/unknown-90001.json" + }, + { + "blank": 0, + "code": 0, + "comment": 0, + "filename": ".secret" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 228, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 183, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 76, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 56, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 623, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 69, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 113, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 63, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 294, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 684, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 233, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 86, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 194, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 24, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 43, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.dbg.json" + }, + { + "blank": 0, + "code": 30, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/0741eeb9b315cb9b0ec518d0b68d9782.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/2d5bbffb16669edfd417b27cee834037.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/812966bfa960758020392658194fda8b.json" + }, + { + "blank": 0, + "code": 1, + "comment": 0, + "filename": "artifacts/build-info/d5b668fee5834f9f49f46dc9b302ec28.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Decode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Decode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Encode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/Encode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/PrecompileStaking.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/PrecompileStaking.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test.dbg.json" + }, + { + "blank": 0, + "code": 73, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test2.dbg.json" + }, + { + "blank": 0, + "code": 31, + "comment": 0, + "filename": "artifacts/contracts/attackContract.sol/test2.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/common/Governable.sol/Governable.dbg.json" + }, + { + "blank": 0, + "code": 267, + "comment": 0, + "filename": "artifacts/contracts/common/Governable.sol/Governable.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/FeeTreasury.sol/FeeTreasury.dbg.json" + }, + { + "blank": 0, + "code": 293, + "comment": 0, + "filename": "artifacts/contracts/FeeTreasury.sol/FeeTreasury.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.dbg.json" + }, + { + "blank": 0, + "code": 180, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.dbg.json" + }, + { + "blank": 0, + "code": 63, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.dbg.json" + }, + { + "blank": 0, + "code": 68, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.dbg.json" + }, + { + "blank": 0, + "code": 113, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IWFX.sol/IWFX.dbg.json" + }, + { + "blank": 0, + "code": 59, + "comment": 0, + "filename": "artifacts/contracts/interfaces/IWFX.sol/IWFX.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/libraries/Decode.sol/Decode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/libraries/Decode.sol/Decode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/libraries/Encode.sol/Encode.dbg.json" + }, + { + "blank": 0, + "code": 10, + "comment": 0, + "filename": "artifacts/contracts/libraries/Encode.sol/Encode.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/MultiCall.sol/MultiCall.dbg.json" + }, + { + "blank": 0, + "code": 254, + "comment": 0, + "filename": "artifacts/contracts/MultiCall.sol/MultiCall.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/RewardDistributor.sol/RewardDistributor.dbg.json" + }, + { + "blank": 0, + "code": 536, + "comment": 0, + "filename": "artifacts/contracts/RewardDistributor.sol/RewardDistributor.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/StakeFXVault.sol/StakeFXVault.dbg.json" + }, + { + "blank": 0, + "code": 1875, + "comment": 0, + "filename": "artifacts/contracts/StakeFXVault.sol/StakeFXVault.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/vaults/BaseVault.sol/BaseVault.dbg.json" + }, + { + "blank": 0, + "code": 980, + "comment": 0, + "filename": "artifacts/contracts/vaults/BaseVault.sol/BaseVault.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/VestedFX.sol/VestedFX.dbg.json" + }, + { + "blank": 0, + "code": 503, + "comment": 0, + "filename": "artifacts/contracts/VestedFX.sol/VestedFX.json" + }, + { + "blank": 0, + "code": 4, + "comment": 0, + "filename": "artifacts/contracts/VestedFXOld.sol/VestedFXOld.dbg.json" + }, + { + "blank": 0, + "code": 516, + "comment": 0, + "filename": "artifacts/contracts/VestedFXOld.sol/VestedFXOld.json" + }, + { + "blank": 200, + "code": 1516, + "comment": 0, + "filename": "cache/solidity-files-cache.json" + }, + { + "blank": 1568, + "code": 83511, + "comment": 0, + "filename": "cache/validations.json" + }, + { + "blank": 5, + "code": 15, + "comment": 9, + "filename": "contracts/common/Governable.sol" + }, + { + "blank": 15, + "code": 64, + "comment": 8, + "filename": "contracts/FeeTreasury.sol" + }, + { + "blank": 18, + "code": 37, + "comment": 12, + "filename": "contracts/imp/PrecompileStaking.sol" + }, + { + "blank": 9, + "code": 9, + "comment": 6, + "filename": "contracts/interfaces/IPrecompileStaking.sol" + }, + { + "blank": 2, + "code": 7, + "comment": 1, + "filename": "contracts/interfaces/IRewardDistributor.sol" + }, + { + "blank": 6, + "code": 7, + "comment": 1, + "filename": "contracts/interfaces/IStakeFXVault.sol" + }, + { + "blank": 7, + "code": 13, + "comment": 1, + "filename": "contracts/interfaces/IVestedFX.sol" + }, + { + "blank": 4, + "code": 6, + "comment": 1, + "filename": "contracts/interfaces/IWFX.sol" + }, + { + "blank": 8, + "code": 47, + "comment": 1, + "filename": "contracts/libraries/Decode.sol" + }, + { + "blank": 7, + "code": 38, + "comment": 1, + "filename": "contracts/libraries/Encode.sol" + }, + { + "blank": 16, + "code": 64, + "comment": 11, + "filename": "contracts/MultiCall.sol" + }, + { + "blank": 24, + "code": 69, + "comment": 9, + "filename": "contracts/RewardDistributor.sol" + }, + { + "blank": 131, + "code": 511, + "comment": 91, + "filename": "contracts/StakeFXVault.sol" + }, + { + "blank": 19, + "code": 76, + "comment": 40, + "filename": "contracts/vaults/BaseVault.sol" + }, + { + "blank": 46, + "code": 144, + "comment": 37, + "filename": "contracts/VestedFX.sol" + }, + { + "blank": 3, + "code": 75, + "comment": 18, + "filename": "hardhat.config.js" + }, + { + "blank": 26, + "code": 16563, + "comment": 0, + "filename": "package-lock.json" + }, + { + "blank": 0, + "code": 22, + "comment": 0, + "filename": "package.json" + }, + { + "blank": 3, + "code": 10, + "comment": 0, + "filename": "README.md" + }, + { + "blank": 38, + "code": 20, + "comment": 76, + "filename": "scripts/deploy.js" + }, + { + "blank": 29, + "code": 89, + "comment": 9, + "filename": "test/Lock.js" + }, + { + "blank": 24, + "code": 38, + "comment": 22, + "filename": "test/test.js" + }, + { + "blank": 0, + "code": 63, + "comment": 0, + "filename": "test/verify.json" + } + ] + } + ] +} \ No newline at end of file diff --git a/out/linecounter.txt b/out/linecounter.txt new file mode 100644 index 0000000..87fb373 --- /dev/null +++ b/out/linecounter.txt @@ -0,0 +1,302 @@ +=============================================================================== +EXTENSION NAME : linecounter +EXTENSION VERSION : 0.2.7 +------------------------------------------------------------------------------- +count time : 2023-09-06 10:59:15 +count workspace : /Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound +total files : 131 +total code lines : 120582 +total comment lines : 423 +total blank lines : 2302 + + statistics + | extension| total code| total comment| total blank|percent| + ------------------------------------------------------------------------- + | .js| 222| 125| 94| 0.18| + | | 11| 0| 0| 0.0091| + | .json| 118912| 0| 1794| 99| + | .md| 10| 0| 3| 0.0083| + | .sol| 1427| 298| 411| 1.2| + ------------------------------------------------------------------------- +.gitignore, code is 11, comment is 0, blank is 0. +.openzeppelin/unknown-530.json, code is 1795, comment is 0, blank is 0. +.openzeppelin/unknown-90001.json, code is 6210, comment is 0, blank is 0. +.secret, code is 0, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.json, code is 228, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.json, code is 183, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json, code is 76, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.json, code is 56, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.json, code is 623, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.json, code is 69, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.json, code is 113, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json, code is 63, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json, code is 294, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.json, code is 684, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.json, code is 233, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.json, code is 86, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.json, code is 194, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.json, code is 43, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.json, code is 30, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/build-info/0741eeb9b315cb9b0ec518d0b68d9782.json, code is 1, comment is 0, blank is 0. +artifacts/build-info/2d5bbffb16669edfd417b27cee834037.json, code is 1, comment is 0, blank is 0. +artifacts/build-info/812966bfa960758020392658194fda8b.json, code is 1, comment is 0, blank is 0. +artifacts/build-info/d5b668fee5834f9f49f46dc9b302ec28.json, code is 1, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Decode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Decode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Encode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Encode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/PrecompileStaking.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/PrecompileStaking.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test.json, code is 73, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test2.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test2.json, code is 31, comment is 0, blank is 0. +artifacts/contracts/common/Governable.sol/Governable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/common/Governable.sol/Governable.json, code is 267, comment is 0, blank is 0. +artifacts/contracts/FeeTreasury.sol/FeeTreasury.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/FeeTreasury.sol/FeeTreasury.json, code is 293, comment is 0, blank is 0. +artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.json, code is 180, comment is 0, blank is 0. +artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.json, code is 63, comment is 0, blank is 0. +artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.json, code is 68, comment is 0, blank is 0. +artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.json, code is 113, comment is 0, blank is 0. +artifacts/contracts/interfaces/IWFX.sol/IWFX.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IWFX.sol/IWFX.json, code is 59, comment is 0, blank is 0. +artifacts/contracts/libraries/Decode.sol/Decode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/libraries/Decode.sol/Decode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/libraries/Encode.sol/Encode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/libraries/Encode.sol/Encode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/MultiCall.sol/MultiCall.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/MultiCall.sol/MultiCall.json, code is 254, comment is 0, blank is 0. +artifacts/contracts/RewardDistributor.sol/RewardDistributor.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/RewardDistributor.sol/RewardDistributor.json, code is 536, comment is 0, blank is 0. +artifacts/contracts/StakeFXVault.sol/StakeFXVault.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/StakeFXVault.sol/StakeFXVault.json, code is 1875, comment is 0, blank is 0. +artifacts/contracts/vaults/BaseVault.sol/BaseVault.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/vaults/BaseVault.sol/BaseVault.json, code is 980, comment is 0, blank is 0. +artifacts/contracts/VestedFX.sol/VestedFX.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/VestedFX.sol/VestedFX.json, code is 503, comment is 0, blank is 0. +artifacts/contracts/VestedFXOld.sol/VestedFXOld.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/VestedFXOld.sol/VestedFXOld.json, code is 516, comment is 0, blank is 0. +cache/solidity-files-cache.json, code is 1516, comment is 0, blank is 200. +cache/validations.json, code is 83511, comment is 0, blank is 1568. +contracts/attackContract.sol, code is 154, comment is 6, blank is 42. +contracts/common/Governable.sol, code is 15, comment is 9, blank is 5. +contracts/FeeTreasury.sol, code is 64, comment is 8, blank is 15. +contracts/imp/PrecompileStaking.sol, code is 37, comment is 12, blank is 18. +contracts/interfaces/IPrecompileStaking.sol, code is 9, comment is 6, blank is 9. +contracts/interfaces/IRewardDistributor.sol, code is 7, comment is 1, blank is 2. +contracts/interfaces/IStakeFXVault.sol, code is 7, comment is 1, blank is 6. +contracts/interfaces/IVestedFX.sol, code is 13, comment is 1, blank is 7. +contracts/interfaces/IWFX.sol, code is 6, comment is 1, blank is 4. +contracts/libraries/Decode.sol, code is 47, comment is 1, blank is 8. +contracts/libraries/Encode.sol, code is 38, comment is 1, blank is 7. +contracts/MultiCall.sol, code is 64, comment is 11, blank is 16. +contracts/RewardDistributor.sol, code is 69, comment is 9, blank is 24. +contracts/StakeFXVault.sol, code is 511, comment is 91, blank is 131. +contracts/vaults/BaseVault.sol, code is 76, comment is 40, blank is 19. +contracts/VestedFX.sol, code is 144, comment is 37, blank is 46. +contracts/VestedFXOld.sol, code is 166, comment is 63, blank is 52. +hardhat.config.js, code is 75, comment is 18, blank is 3. +package-lock.json, code is 16563, comment is 0, blank is 26. +package.json, code is 22, comment is 0, blank is 0. +README.md, code is 10, comment is 0, blank is 3. +scripts/deploy.js, code is 20, comment is 76, blank is 38. +test/Lock.js, code is 89, comment is 9, blank is 29. +test/test.js, code is 38, comment is 22, blank is 24. +test/verify.json, code is 63, comment is 0, blank is 0. +=============================================================================== +=============================================================================== +EXTENSION NAME : linecounter +EXTENSION VERSION : 0.2.7 +------------------------------------------------------------------------------- +count time : 2023-09-06 11:01:23 +count workspace : /Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound +total files : 129 +total code lines : 120262 +total comment lines : 354 +total blank lines : 2208 + + statistics + | extension| total code| total comment| total blank|percent| + ------------------------------------------------------------------------- + | | 11| 0| 0| 0.0091| + | .js| 222| 125| 94| 0.18| + | .md| 10| 0| 3| 0.0083| + | .sol| 1107| 229| 317| 0.92| + | .json| 118912| 0| 1794| 99| + ------------------------------------------------------------------------- +.gitignore, code is 11, comment is 0, blank is 0. +.openzeppelin/unknown-530.json, code is 1795, comment is 0, blank is 0. +.openzeppelin/unknown-90001.json, code is 6210, comment is 0, blank is 0. +.secret, code is 0, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol/AccessControlUpgradeable.json, code is 228, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol/IAccessControlUpgradeable.json, code is 183, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json, code is 76, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol/IERC1822ProxiableUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol/IERC1967Upgradeable.json, code is 56, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol/IERC4626Upgradeable.json, code is 623, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol/IBeaconUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol/ERC1967UpgradeUpgradeable.json, code is 69, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol/UUPSUpgradeable.json, code is 113, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json, code is 63, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol/ERC20Upgradeable.json, code is 294, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol/ERC4626Upgradeable.json, code is 684, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol/IERC20MetadataUpgradeable.json, code is 233, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.json, code is 86, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.json, code is 194, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json, code is 24, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol/ERC165Upgradeable.json, code is 43, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol/IERC165Upgradeable.json, code is 30, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol/MathUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol/SafeMathUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol/SignedMathUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol/StorageSlotUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol/StringsUpgradeable.json, code is 10, comment is 0, blank is 0. +artifacts/build-info/0741eeb9b315cb9b0ec518d0b68d9782.json, code is 1, comment is 0, blank is 0. +artifacts/build-info/2d5bbffb16669edfd417b27cee834037.json, code is 1, comment is 0, blank is 0. +artifacts/build-info/812966bfa960758020392658194fda8b.json, code is 1, comment is 0, blank is 0. +artifacts/build-info/d5b668fee5834f9f49f46dc9b302ec28.json, code is 1, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Decode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Decode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Encode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/Encode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/PrecompileStaking.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/PrecompileStaking.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test.json, code is 73, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test2.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/attackContract.sol/test2.json, code is 31, comment is 0, blank is 0. +artifacts/contracts/common/Governable.sol/Governable.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/common/Governable.sol/Governable.json, code is 267, comment is 0, blank is 0. +artifacts/contracts/FeeTreasury.sol/FeeTreasury.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/FeeTreasury.sol/FeeTreasury.json, code is 293, comment is 0, blank is 0. +artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/imp/PrecompileStaking.sol/PrecompileStaking.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IPrecompileStaking.sol/IPrecompileStaking.json, code is 180, comment is 0, blank is 0. +artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IRewardDistributor.sol/IRewardDistributor.json, code is 63, comment is 0, blank is 0. +artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IStakeFXVault.sol/IStakeFXVault.json, code is 68, comment is 0, blank is 0. +artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IVestedFX.sol/IVestedFX.json, code is 113, comment is 0, blank is 0. +artifacts/contracts/interfaces/IWFX.sol/IWFX.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/interfaces/IWFX.sol/IWFX.json, code is 59, comment is 0, blank is 0. +artifacts/contracts/libraries/Decode.sol/Decode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/libraries/Decode.sol/Decode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/libraries/Encode.sol/Encode.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/libraries/Encode.sol/Encode.json, code is 10, comment is 0, blank is 0. +artifacts/contracts/MultiCall.sol/MultiCall.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/MultiCall.sol/MultiCall.json, code is 254, comment is 0, blank is 0. +artifacts/contracts/RewardDistributor.sol/RewardDistributor.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/RewardDistributor.sol/RewardDistributor.json, code is 536, comment is 0, blank is 0. +artifacts/contracts/StakeFXVault.sol/StakeFXVault.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/StakeFXVault.sol/StakeFXVault.json, code is 1875, comment is 0, blank is 0. +artifacts/contracts/vaults/BaseVault.sol/BaseVault.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/vaults/BaseVault.sol/BaseVault.json, code is 980, comment is 0, blank is 0. +artifacts/contracts/VestedFX.sol/VestedFX.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/VestedFX.sol/VestedFX.json, code is 503, comment is 0, blank is 0. +artifacts/contracts/VestedFXOld.sol/VestedFXOld.dbg.json, code is 4, comment is 0, blank is 0. +artifacts/contracts/VestedFXOld.sol/VestedFXOld.json, code is 516, comment is 0, blank is 0. +cache/solidity-files-cache.json, code is 1516, comment is 0, blank is 200. +cache/validations.json, code is 83511, comment is 0, blank is 1568. +contracts/common/Governable.sol, code is 15, comment is 9, blank is 5. +contracts/FeeTreasury.sol, code is 64, comment is 8, blank is 15. +contracts/imp/PrecompileStaking.sol, code is 37, comment is 12, blank is 18. +contracts/interfaces/IPrecompileStaking.sol, code is 9, comment is 6, blank is 9. +contracts/interfaces/IRewardDistributor.sol, code is 7, comment is 1, blank is 2. +contracts/interfaces/IStakeFXVault.sol, code is 7, comment is 1, blank is 6. +contracts/interfaces/IVestedFX.sol, code is 13, comment is 1, blank is 7. +contracts/interfaces/IWFX.sol, code is 6, comment is 1, blank is 4. +contracts/libraries/Decode.sol, code is 47, comment is 1, blank is 8. +contracts/libraries/Encode.sol, code is 38, comment is 1, blank is 7. +contracts/MultiCall.sol, code is 64, comment is 11, blank is 16. +contracts/RewardDistributor.sol, code is 69, comment is 9, blank is 24. +contracts/StakeFXVault.sol, code is 511, comment is 91, blank is 131. +contracts/vaults/BaseVault.sol, code is 76, comment is 40, blank is 19. +contracts/VestedFX.sol, code is 144, comment is 37, blank is 46. +hardhat.config.js, code is 75, comment is 18, blank is 3. +package-lock.json, code is 16563, comment is 0, blank is 26. +package.json, code is 22, comment is 0, blank is 0. +README.md, code is 10, comment is 0, blank is 3. +scripts/deploy.js, code is 20, comment is 76, blank is 38. +test/Lock.js, code is 89, comment is 9, blank is 29. +test/test.js, code is 38, comment is 22, blank is 24. +test/verify.json, code is 63, comment is 0, blank is 0. +=============================================================================== diff --git a/scripts/deploy.js b/scripts/deploy.js index 130dfec..28d22db 100644 --- a/scripts/deploy.js +++ b/scripts/deploy.js @@ -1,4 +1,4 @@ -// npx hardhat run scripts/deploy.js --network fxMainnet +// npx hardhat run scripts/deploy.js --network local // npx hardhat verify --constructor-args arguments.js --network goerli 0x26f2e0dEAE57b33bFEc2DCD958d04b154e69f405 // npx hardhat verify --network avalanche 0xa49f2a936770eb6ce5D94A455D9598B6cbbec058 @@ -21,7 +21,7 @@ async function main() { // const reward = "0xc8B4d3e67238e38B20d38908646fF6F4F48De5EC" // const stFX= "0x5c24B402b4b4550CF94227813f3547B94774c1CB" - const vest= "0x37f716f6693EB2681879642e38BbD9e922A53CDf" + // const vest= "0x37f716f6693EB2681879642e38BbD9e922A53CDf" // const treasury= "0xe48C3eA37D4956580799d90a4601887d77A57d55" // const distributor= "0xea505C49B43CD0F9Ed3b40D77CAF1e32b0097328" @@ -33,19 +33,71 @@ async function main() { // const governor = "0xfe6e9353000a31B9C87F4EAE411C89b1E355Ba50" // const asset = "0x0000000000000000000000000000000000000000" - // const stFX= "0x5aF7AC9DfE8C894E88a197033E550614f2214665" + const stFX = "0x5aF7AC9DfE8C894E88a197033E550614f2214665" // const vest= "0x8E1D972703c0BbE65cbBa42bd75D0Eb41B8397b5" // const treasury= "0x1dB21fF54414f62FD65D98c6D5FEdCe6C07CeF10" // const reward = "0x28630568bC33Ead4f4A48c0637Dae30aC1114332" + /* ******** Testnet(Dev) ******** */ + + // const owner = "0xfe6e9353000a31B9C87F4EAE411C89b1E355Ba50" + // const governor = "0xfe6e9353000a31B9C87F4EAE411C89b1E355Ba50" + // const asset = "0x0000000000000000000000000000000000000000" + + // const stFX= "0x18D094D43140Aaa9BaD82dd08d2dDDa8a6239777" + // const vest= "0x61f4139abbEB9Af11B9c07FBa862E48e823294CA" + // const treasury= "0xF47cB2369aa34B624c0De2008308e775E821F585" + // const distributor= "0x41c4115d5aCDff238eefCa106402Da97bD6DEe77" + // const reward = "0x18D094D43140Aaa9BaD82dd08d2dDDa8a6239777" + + const owner = "0x4e3DA49cc22694D53F4a71e4d4BfdFB2BF272887" + const dummy = "0x0000000000000000000000000000000000000000" + + +// ################################################################################################################################################################ + + + /***************************************************** + ***************** Deploy EsBAVA ********************* + *****************************************************/ + + // const EsBAVA = await ethers.getContractFactory("EsBAVA"); + // const esBAVA = await upgrades.deployProxy(EsBAVA, [owner, dummy, dummy, dummy], {kind: "uups", timeout: '0', pollingInterval: '1000'}); + + // // await esBAVA.waitForDeployment(); + // console.log("Contract address:", esBAVA.address); + + + /***************************************************** + ***************** Deploy Vester ******************** + *****************************************************/ + + // const bavaFxCore = "0xc8b4d3e67238e38b20d38908646ff6f4f48de5ec" + // const esBAVAFxCore = "0x4dE4a1AC6Adf86E492Cf36084B7d92B349b95fa3" + + // const bavaDhouby = "0xc7e56EEc629D3728fE41baCa2f6BFc502096f94E" + // const esBAVADhouby = "0xd00D29C1f5587cbbF483DAE889391b702adcD29F" + + // const Vester = await ethers.getContractFactory("Vester"); + // // const vester = await upgrades.upgradeProxy("0x41c4115d5aCDff238eefCa106402Da97bD6DEe77", Vester, {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // const vester = await upgrades.deployProxy(Vester, ["Vested BAVA", "veBAVA", "94608000", esBAVAFxCore, bavaFxCore, owner, owner], {kind: "uups", timeout: '0', pollingInterval: '1000'}); + + // // await vester.waitForDeployment(); + // console.log("Contract address:", vester.address); + + + + + // ============ Deploy StakeFXVault ============ - // const StakeFXVault = await ethers.getContractFactory("StakeFXVault"); - // const stakeFXVault = await upgrades.upgradeProxy(stFX, StakeFXVault, {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // const stakeFXVault = await upgrades.deployProxy(StakeFXVault, [asset, owner, governor], {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // await stakeFXVault.deployed(); + const StakeFXVault = await ethers.getContractFactory("StakeFXVaultV3"); + const stakeFXVault = await upgrades.upgradeProxy(stFX, StakeFXVault, {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // // // const stakeFXVault = await upgrades.deployProxy(StakeFXVault, [asset, owner, governor], {kind: "uups", timeout: '0', pollingInterval: '1000'}); + await stakeFXVault.deployed(); + // await stakeFXVault.addValidator("fxvaloper17w0adeg64ky0daxwd2ugyuneellmjgnx3uhcc3", "1000") // await stakeFXVault.addValidator("fxvaloper1as2rwvnayy30pzjy7aw35dcsja6g98nd87r8vp", "1000") // European University Cyprus // await stakeFXVault.addValidator("fxvaloper1ms606vz2zrxw7752y5ae8z4zyp52ajjacv9qyd", "1000") // Miami // await stakeFXVault.addValidator("fxvaloper19psvqem8jafc5ydg4cnh0t2m04ngw9gfqkeceu", "1000") // Blindgotchi @@ -57,7 +109,7 @@ async function main() { // await stakeFXVault.addValidator("fxvaloper1v65jk0gvzqdghcclldex08cddc38dau6zty3j5", "600") // await stakeFXVault.addValidator("fxvaloper158gmj69jpfsrvee3a220afjs952p4m6kltc67h", "1200") // await stakeFXVault.addValidator("fxvaloper1sfw4q2uj8ag79usl562u5wz2rwgzavs0fw4tr2", "200") - // console.log("Contract address:", stakeFXVault.address); + console.log("Contract address:", stakeFXVault.address); // ============ Deploy FXFeesTreasury ============ @@ -70,29 +122,29 @@ async function main() { // ============ Deploy VestedFX ============ - const VestedFX = await ethers.getContractFactory("VestedFX"); - const vestedFX = await upgrades.upgradeProxy(vest, VestedFX, {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // const vestedFX = await upgrades.deployProxy(VestedFX, [stFX, fxFeesTreasury.address], {kind: "uups", timeout: '0', pollingInterval: '1000'}); - await vestedFX.deployed(); + // const VestedFX = await ethers.getContractFactory("VestedFX"); + // // const vestedFX = await upgrades.upgradeProxy(vest, VestedFX, {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // const vestedFX = await upgrades.deployProxy(VestedFX, [stFX, treasury], {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // await vestedFX.deployed(); - console.log("Contract address:", vestedFX.address); + // console.log("Contract address:", vestedFX.address); // ============ Deploy RewardDistributor ============ // const RewardDistributor = await ethers.getContractFactory("RewardDistributor"); // const rewardDistributor = await upgrades.upgradeProxy("0x5ef13FBa677536Fd98C1c98E45D1201774feCC02", RewardDistributor, {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // const rewardDistributor = await upgrades.deployProxy(RewardDistributor, [reward, stFX, owner, owner], {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // await rewardDistributor.deployed(); + // // const rewardDistributor = await upgrades.deployProxy(RewardDistributor, [reward, stFX, owner, owner], {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // // await rewardDistributor.deployed(); // console.log("Contract address:", rewardDistributor.address); // ============ Deploy MultiCall ============ // const MultiCall = await ethers.getContractFactory("MultiCall"); - // // const multiCall = await upgrades.upgradeProxy("0x9A434d8253BC8A55e3e2de19275A71eA8Be63Cd4", MultiCall, {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // const multiCall = await upgrades.deployProxy(MultiCall, [stFX], {kind: "uups", timeout: '0', pollingInterval: '1000'}); - // // await multiCall.deployed(); + // const multiCall = await upgrades.upgradeProxy("0xF5E657e315d8766e0841eE83DeEE05aa836Cc8ce", MultiCall, {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // // const multiCall = await upgrades.deployProxy(MultiCall, [stFX], {kind: "uups", timeout: '0', pollingInterval: '1000'}); + // await multiCall.deployed(); // console.log("Contract address:", multiCall.address); @@ -105,19 +157,29 @@ async function main() { // const distributor= "0xea505C49B43CD0F9Ed3b40D77CAF1e32b0097328" // const multicall= "0xF5E657e315d8766e0841eE83DeEE05aa836Cc8ce" - // const stakeFXVault = await ethers.getContractAt("StakeFXVault", stFX); - // // const fxFeesTreasury = await ethers.getContractAt("FeeTreasury", treasury); - // await stakeFXVault.updateConfigs(tokens("0.1"),tokens("100"),tokens("10"),tokens("10")); + // const stakeFXVault = await ethers.getContractAt("StakeFXVaultV2", stFX); + // const fxFeesTreasury = await ethers.getContractAt("FeeTreasury", treasury); + // const rewardDistributor = await ethers.getContractAt("RewardDistributor", distributor); + + // await stakeFXVault.updateConfigs(tokens("1"),tokens("1000000"),tokens("10"),tokens("10")); // await stakeFXVault.updateFees("690","10","50"); // await stakeFXVault.addValidator("fxvaloper1a73plz6w7fc8ydlwxddanc7a239kk45jnl9xwj", "1000") // Singapore // await stakeFXVault.addValidator("fxvaloper1srkazumnkle6uzmdvqq68df9gglylp3pkhuwna", "1000") // Litecoin - // await stakeFXVault.updateVestedFX(vestedFX.address); - // await stakeFXVault.updateFeeTreasury(fxFeesTreasury.address); - // await stakeFXVault.updateDistributor(rewardDistributor.address); + // await stakeFXVault.updateVestedFX(vest); + // await stakeFXVault.updateFeeTreasury(treasury); + // await stakeFXVault.updateDistributor(distributor); + + // await stakeFXVault.grantRole("0x4f574e45525f524f4c4500000000000000000000000000000000000000000000", "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") + // await stakeFXVault.grantRole("0x4f50455241544f525f524f4c4500000000000000000000000000000000000000", "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") + // await stakeFXVault.grantRole("0x474f5645524e4f525f524f4c4500000000000000000000000000000000000000", "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") + // console.log("Contract address:", stakeFXVault.address); + // const data = [] = await stakeFXVault.getVaultConfigs(); + // console.log(data) + // await stakeFXVault.stake({value: tokens("0.1")}); - // await fxFeesTreasury.updateVestedFX(vestedFX.address); + // await fxFeesTreasury.updateVestedFX(vest); // console.log("Done0"); // await rewardDistributor.updateLastDistributionTime(); diff --git a/slither.db.json b/slither.db.json new file mode 100644 index 0000000..a45bfca --- /dev/null +++ b/slither.db.json @@ -0,0 +1 @@ +[{"elements": [{"type": "function", "name": "recoverFx", "source_mapping": {"start": 25931, "length": 280, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [689, 690, 691, 692, 693, 694, 695, 696], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "recoverFx(uint256,address)"}}, {"type": "node", "name": "(success) = recipient.call{value: safeAmount}()", "source_mapping": {"start": 26101, "length": 56, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [694], "starting_column": 9, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "recoverFx", "source_mapping": {"start": 25931, "length": 280, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [689, 690, 691, 692, 693, 694, 695, 696], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "recoverFx(uint256,address)"}}}}], "description": "StakeFXVault.recoverFx(uint256,address) (contracts/StakeFXVault.sol#689-696) sends eth to arbitrary user\n\tDangerous calls:\n\t- (success) = recipient.call{value: safeAmount}() (contracts/StakeFXVault.sol#694)\n", "markdown": "[StakeFXVault.recoverFx(uint256,address)](contracts/StakeFXVault.sol#L689-L696) sends eth to arbitrary user\n\tDangerous calls:\n\t- [(success) = recipient.call{value: safeAmount}()](contracts/StakeFXVault.sol#L694)\n", "first_markdown_element": "contracts/StakeFXVault.sol#L689-L696", "id": "e676fec80cd17c628b69f3dde0982ae7a7f5560e9a4b5843bfa93df467b80c51", "check": "arbitrary-send", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}, {"type": "node", "name": "(sharesAmount,delegationAmount) = _delegation(val,msg.sender)", "source_mapping": {"start": 6669, "length": 79, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [169], "starting_column": 9, "ending_column": 88}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "(result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del))", "source_mapping": {"start": 1900, "length": 92, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 101}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegation", "source_mapping": {"start": 1794, "length": 300, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [47, 48, 49, 50, 51, 52], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegation(string,address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "delegationReward = getTotalDelegationRewards()", "source_mapping": {"start": 6820, "length": 54, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [172], "starting_column": 9, "ending_column": 63}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "(result,data) = _stakingAddress.staticcall(Encode.delegationRewards(_val,_del))", "source_mapping": {"start": 2204, "length": 99, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [55], "starting_column": 9, "ending_column": 108}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegationRewards", "source_mapping": {"start": 2100, "length": 319, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [54, 55, 56, 57, 58, 59], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegationRewards(string,address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "compound()", "source_mapping": {"start": 6942, "length": 10, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [174], "starting_column": 13, "ending_column": 23}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "(result,data) = _stakingAddress.call(Encode.withdraw(_val))", "source_mapping": {"start": 1239, "length": 78, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [34], "starting_column": 9, "ending_column": 87}, "type_specific_fields": {"parent": {"type": "function", "name": "_withdraw", "source_mapping": {"start": 1163, "length": 252, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [33, 34, 35, 36, 37, 38], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_withdraw(string)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del))", "source_mapping": {"start": 1900, "length": 92, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 101}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegation", "source_mapping": {"start": 1794, "length": 300, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [47, 48, 49, 50, 51, 52], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegation(string,address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(result,data) = _stakingAddress.staticcall(Encode.delegationRewards(_val,_del))", "source_mapping": {"start": 2204, "length": 99, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [55], "starting_column": 9, "ending_column": 108}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegationRewards", "source_mapping": {"start": 2100, "length": 319, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [54, 55, 56, 57, 58, 59], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegationRewards(string,address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(result,data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val))", "source_mapping": {"start": 655, "length": 94, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [20], "starting_column": 9, "ending_column": 103}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegate", "source_mapping": {"start": 553, "length": 294, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegate(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(successTreasury) = treasury.call{value: feeProtocol}()", "source_mapping": {"start": 8517, "length": 64, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [215], "starting_column": 9, "ending_column": 73}, "type_specific_fields": {"parent": {"type": "function", "name": "compound", "source_mapping": {"start": 7995, "length": 783, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "compound()"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(successUser) = user.call{value: feeCompounder}()", "source_mapping": {"start": 8591, "length": 58, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [216], "starting_column": 9, "ending_column": 67}, "type_specific_fields": {"parent": {"type": "function", "name": "compound", "source_mapping": {"start": 7995, "length": 783, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "compound()"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "_claim(msg.sender,msg.sender)", "source_mapping": {"start": 6972, "length": 30, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [176], "starting_column": 9, "ending_column": 39}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "blockReward = IRewardDistributor(distributor).distribute()", "source_mapping": {"start": 18335, "length": 66, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [484], "starting_column": 9, "ending_column": 75}, "type_specific_fields": {"parent": {"type": "function", "name": "_updateRewards", "source_mapping": {"start": 18276, "length": 1212, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "_updateRewards(address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "returndata = address(token).functionCall(data,SafeERC20: low-level call failed)", "source_mapping": {"start": 5735, "length": 95, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "is_dependency": true, "lines": [122], "starting_column": 9, "ending_column": 104}, "type_specific_fields": {"parent": {"type": "function", "name": "_callOptionalReturn", "source_mapping": {"start": 5305, "length": 653, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "is_dependency": true, "lines": [117, 118, 119, 120, 121, 122, 123, 124], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "SafeERC20Upgradeable", "source_mapping": {"start": 734, "length": 6343, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol", "is_dependency": true, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143], "starting_column": 1, "ending_column": 2}}, "signature": "_callOptionalReturn(IERC20Upgradeable,bytes)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(success,returndata) = target.call{value: value}(data)", "source_mapping": {"start": 5456, "length": 73, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "is_dependency": true, "lines": [135], "starting_column": 9, "ending_column": 82}, "type_specific_fields": {"parent": {"type": "function", "name": "functionCallWithValue", "source_mapping": {"start": 5176, "length": 446, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "is_dependency": true, "lines": [128, 129, 130, 131, 132, 133, 134, 135, 136, 137], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "AddressUpgradeable", "source_mapping": {"start": 194, "length": 9180, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "is_dependency": true, "lines": [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244], "starting_column": 1, "ending_column": 2}}, "signature": "functionCallWithValue(address,bytes,uint256,string)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "IERC20Upgradeable(rewardToken()).safeTransfer(receiver,tokenAmount)", "source_mapping": {"start": 18110, "length": 68, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [476], "starting_column": 13, "ending_column": 81}, "type_specific_fields": {"parent": {"type": "function", "name": "_claim", "source_mapping": {"start": 17817, "length": 453, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "_claim(address,address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "totalAsset = totalAssets()", "source_mapping": {"start": 7021, "length": 34, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [178], "starting_column": 9, "ending_column": 43}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "(result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del))", "source_mapping": {"start": 1900, "length": 92, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [48], "starting_column": 9, "ending_column": 101}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegation", "source_mapping": {"start": 1794, "length": 300, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [47, 48, 49, 50, 51, 52], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegation(string,address)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(fxAmountToTransfer,returnRewards) = _transferFromShares(val,msg.sender,address(this),amount)", "source_mapping": {"start": 7282, "length": 113, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [183], "starting_column": 9, "ending_column": 122}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "(result,data) = _stakingAddress.call(Encode.transferFromShares(_val,_from,_to,_shares))", "source_mapping": {"start": 1561, "length": 109, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [41], "starting_column": 9, "ending_column": 118}, "type_specific_fields": {"parent": {"type": "function", "name": "_transferFromShares", "source_mapping": {"start": 1421, "length": 367, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [40, 41, 42, 43, 44, 45], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_transferFromShares(string,address,address,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "compound()", "source_mapping": {"start": 6942, "length": 10, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [174], "starting_column": 13, "ending_column": 23}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(result,data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val))", "source_mapping": {"start": 655, "length": 94, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [20], "starting_column": 9, "ending_column": 103}, "type_specific_fields": {"parent": {"type": "function", "name": "_delegate", "source_mapping": {"start": 553, "length": 294, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "PrecompileStaking", "source_mapping": {"start": 282, "length": 2430, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_relative": "contracts/imp/PrecompileStaking.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/imp/PrecompileStaking.sol", "filename_short": "contracts/imp/PrecompileStaking.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 1, "ending_column": 0}}, "signature": "_delegate(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(successTreasury) = treasury.call{value: feeProtocol}()", "source_mapping": {"start": 8517, "length": 64, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [215], "starting_column": 9, "ending_column": 73}, "type_specific_fields": {"parent": {"type": "function", "name": "compound", "source_mapping": {"start": 7995, "length": 783, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "compound()"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(successUser) = user.call{value: feeCompounder}()", "source_mapping": {"start": 8591, "length": 58, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [216], "starting_column": 9, "ending_column": 67}, "type_specific_fields": {"parent": {"type": "function", "name": "compound", "source_mapping": {"start": 7995, "length": 783, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "compound()"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "_claim(msg.sender,msg.sender)", "source_mapping": {"start": 6972, "length": 30, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [176], "starting_column": 9, "ending_column": 39}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "(success,returndata) = target.call{value: value}(data)", "source_mapping": {"start": 5456, "length": 73, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "is_dependency": true, "lines": [135], "starting_column": 9, "ending_column": 82}, "type_specific_fields": {"parent": {"type": "function", "name": "functionCallWithValue", "source_mapping": {"start": 5176, "length": 446, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "is_dependency": true, "lines": [128, 129, 130, 131, 132, 133, 134, 135, 136, 137], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "AddressUpgradeable", "source_mapping": {"start": 194, "length": 9180, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol", "is_dependency": true, "lines": [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244], "starting_column": 1, "ending_column": 2}}, "signature": "functionCallWithValue(address,bytes,uint256,string)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "pendingFxReward += returnRewards", "source_mapping": {"start": 7406, "length": 32, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [185], "starting_column": 9, "ending_column": 41}, "type_specific_fields": {"parent": {"type": "function", "name": "entrustDelegatedShare", "source_mapping": {"start": 6520, "length": 1279, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "StakeFXVault", "source_mapping": {"start": 984, "length": 25762, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_relative": "contracts/StakeFXVault.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/contracts/StakeFXVault.sol", "filename_short": "contracts/StakeFXVault.sol", "is_dependency": false, "lines": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718], "starting_column": 1, "ending_column": 0}}, "signature": "entrustDelegatedShare(string,uint256)"}}}, "additional_fields": {"underlying_type": "variables_written", "variable_name": "pendingFxReward"}}], "description": "Reentrancy in StakeFXVault.entrustDelegatedShare(string,uint256) (contracts/StakeFXVault.sol#166-194):\n\tExternal calls:\n\t- (sharesAmount,delegationAmount) = _delegation(val,msg.sender) (contracts/StakeFXVault.sol#169)\n\t\t- (result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del)) (contracts/imp/PrecompileStaking.sol#48)\n\t- delegationReward = getTotalDelegationRewards() (contracts/StakeFXVault.sol#172)\n\t\t- (result,data) = _stakingAddress.staticcall(Encode.delegationRewards(_val,_del)) (contracts/imp/PrecompileStaking.sol#55)\n\t- compound() (contracts/StakeFXVault.sol#174)\n\t\t- (result,data) = _stakingAddress.call(Encode.withdraw(_val)) (contracts/imp/PrecompileStaking.sol#34)\n\t\t- (result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del)) (contracts/imp/PrecompileStaking.sol#48)\n\t\t- (result,data) = _stakingAddress.staticcall(Encode.delegationRewards(_val,_del)) (contracts/imp/PrecompileStaking.sol#55)\n\t\t- (result,data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val)) (contracts/imp/PrecompileStaking.sol#20)\n\t\t- (successTreasury) = treasury.call{value: feeProtocol}() (contracts/StakeFXVault.sol#215)\n\t\t- (successUser) = user.call{value: feeCompounder}() (contracts/StakeFXVault.sol#216)\n\t- _claim(msg.sender,msg.sender) (contracts/StakeFXVault.sol#176)\n\t\t- blockReward = IRewardDistributor(distributor).distribute() (contracts/StakeFXVault.sol#484)\n\t\t- returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol#122)\n\t\t- (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#135)\n\t\t- IERC20Upgradeable(rewardToken()).safeTransfer(receiver,tokenAmount) (contracts/StakeFXVault.sol#476)\n\t- totalAsset = totalAssets() (contracts/StakeFXVault.sol#178)\n\t\t- (result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del)) (contracts/imp/PrecompileStaking.sol#48)\n\t- (fxAmountToTransfer,returnRewards) = _transferFromShares(val,msg.sender,address(this),amount) (contracts/StakeFXVault.sol#183)\n\t\t- (result,data) = _stakingAddress.call(Encode.transferFromShares(_val,_from,_to,_shares)) (contracts/imp/PrecompileStaking.sol#41)\n\tExternal calls sending eth:\n\t- compound() (contracts/StakeFXVault.sol#174)\n\t\t- (result,data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val)) (contracts/imp/PrecompileStaking.sol#20)\n\t\t- (successTreasury) = treasury.call{value: feeProtocol}() (contracts/StakeFXVault.sol#215)\n\t\t- (successUser) = user.call{value: feeCompounder}() (contracts/StakeFXVault.sol#216)\n\t- _claim(msg.sender,msg.sender) (contracts/StakeFXVault.sol#176)\n\t\t- (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#135)\n\tState variables written after the call(s):\n\t- pendingFxReward += returnRewards (contracts/StakeFXVault.sol#185)\n", "markdown": "Reentrancy in [StakeFXVault.entrustDelegatedShare(string,uint256)](contracts/StakeFXVault.sol#L166-L194):\n\tExternal calls:\n\t- [(sharesAmount,delegationAmount) = _delegation(val,msg.sender)](contracts/StakeFXVault.sol#L169)\n\t\t- [(result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del))](contracts/imp/PrecompileStaking.sol#L48)\n\t- [delegationReward = getTotalDelegationRewards()](contracts/StakeFXVault.sol#L172)\n\t\t- [(result,data) = _stakingAddress.staticcall(Encode.delegationRewards(_val,_del))](contracts/imp/PrecompileStaking.sol#L55)\n\t- [compound()](contracts/StakeFXVault.sol#L174)\n\t\t- [(result,data) = _stakingAddress.call(Encode.withdraw(_val))](contracts/imp/PrecompileStaking.sol#L34)\n\t\t- [(result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del))](contracts/imp/PrecompileStaking.sol#L48)\n\t\t- [(result,data) = _stakingAddress.staticcall(Encode.delegationRewards(_val,_del))](contracts/imp/PrecompileStaking.sol#L55)\n\t\t- [(result,data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val))](contracts/imp/PrecompileStaking.sol#L20)\n\t\t- [(successTreasury) = treasury.call{value: feeProtocol}()](contracts/StakeFXVault.sol#L215)\n\t\t- [(successUser) = user.call{value: feeCompounder}()](contracts/StakeFXVault.sol#L216)\n\t- [_claim(msg.sender,msg.sender)](contracts/StakeFXVault.sol#L176)\n\t\t- [blockReward = IRewardDistributor(distributor).distribute()](contracts/StakeFXVault.sol#L484)\n\t\t- [returndata = address(token).functionCall(data,SafeERC20: low-level call failed)](node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol#L122)\n\t\t- [(success,returndata) = target.call{value: value}(data)](node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#L135)\n\t\t- [IERC20Upgradeable(rewardToken()).safeTransfer(receiver,tokenAmount)](contracts/StakeFXVault.sol#L476)\n\t- [totalAsset = totalAssets()](contracts/StakeFXVault.sol#L178)\n\t\t- [(result,data) = _stakingAddress.staticcall(Encode.delegation(_val,_del))](contracts/imp/PrecompileStaking.sol#L48)\n\t- [(fxAmountToTransfer,returnRewards) = _transferFromShares(val,msg.sender,address(this),amount)](contracts/StakeFXVault.sol#L183)\n\t\t- [(result,data) = _stakingAddress.call(Encode.transferFromShares(_val,_from,_to,_shares))](contracts/imp/PrecompileStaking.sol#L41)\n\tExternal calls sending eth:\n\t- [compound()](contracts/StakeFXVault.sol#L174)\n\t\t- [(result,data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val))](contracts/imp/PrecompileStaking.sol#L20)\n\t\t- [(successTreasury) = treasury.call{value: feeProtocol}()](contracts/StakeFXVault.sol#L215)\n\t\t- [(successUser) = user.call{value: feeCompounder}()](contracts/StakeFXVault.sol#L216)\n\t- [_claim(msg.sender,msg.sender)](contracts/StakeFXVault.sol#L176)\n\t\t- [(success,returndata) = target.call{value: value}(data)](node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol#L135)\n\tState variables written after the call(s):\n\t- [pendingFxReward += returnRewards](contracts/StakeFXVault.sol#L185)\n", "first_markdown_element": "contracts/StakeFXVault.sol#L166-L194", "id": "79410629cf4be2c8239b6e0969e80588e82765ab64de6012371326727564ac22", "check": "reentrancy-eth", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "__gap", "source_mapping": {"start": 8820, "length": 25, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "is_dependency": true, "lines": [260], "starting_column": 5, "ending_column": 30}, "type_specific_fields": {"parent": {"type": "contract", "name": "AccessControlUpgradeable", "source_mapping": {"start": 2019, "length": 6829, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol", "is_dependency": true, "lines": [51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261], "starting_column": 1, "ending_column": 2}}}}, {"type": "variable", "name": "__gap", "source_mapping": {"start": 1491, "length": 25, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "is_dependency": true, "lines": [41], "starting_column": 5, "ending_column": 30}, "type_specific_fields": {"parent": {"type": "contract", "name": "ERC165Upgradeable", "source_mapping": {"start": 783, "length": 736, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol", "is_dependency": true, "lines": [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "starting_column": 1, "ending_column": 2}}}}, {"type": "variable", "name": "__gap", "source_mapping": {"start": 1316, "length": 25, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "is_dependency": true, "lines": [36], "starting_column": 5, "ending_column": 30}, "type_specific_fields": {"parent": {"type": "contract", "name": "ContextUpgradeable", "source_mapping": {"start": 651, "length": 693, "filename_used": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "filename_relative": "node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "filename_absolute": "/Users/cheekeatlim/Desktop/FXProject/smartContract/fxLP_delegate_compound/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "filename_short": "node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol", "is_dependency": true, "lines": [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37], "starting_column": 1, "ending_column": 2}}}}], "description": "AccessControlUpgradeable.__gap (node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#260) shadows:\n\t- ERC165Upgradeable.__gap (node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#41)\n\t- ContextUpgradeable.__gap (node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#36)\n", "markdown": "[AccessControlUpgradeable.__gap](node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#L260) shadows:\n\t- [ERC165Upgradeable.__gap](node_modules/@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol#L41)\n\t- [ContextUpgradeable.__gap](node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol#L36)\n", "first_markdown_element": "node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol#L260", "id": "2ebe200d7dce5f287d47b5452eb3204c806e3ef40d9d51bf6dffad048fd7e73d", "check": "shadowing-state", "impact": "High", "confidence": "High"}] \ No newline at end of file diff --git a/slitherCheck.txt b/slitherCheck.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/AddValidator.js b/test/AddValidator.js new file mode 100644 index 0000000..07dffa9 --- /dev/null +++ b/test/AddValidator.js @@ -0,0 +1,28 @@ +const { StakeFXVaultV2Address, validator2 } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("AddValidator", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser } = await loadContractFixture(); + await stFX.connect(authorizedUser).addValidator(validator2, 1); + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthUser of notAuthorizedUsers) { + await expect( + stFX.connect(notAuthUser).callStatic.addValidator(validator2, 1) + ).rejectedWith(Error, AccessControl); + } + }); +}); \ No newline at end of file diff --git a/test/Lock.js b/test/Lock.js deleted file mode 100644 index 6a161e6..0000000 --- a/test/Lock.js +++ /dev/null @@ -1,126 +0,0 @@ -const { - time, - loadFixture, -} = require("@nomicfoundation/hardhat-network-helpers"); -const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); -const { expect } = require("chai"); - -describe("Lock", function () { - // We define a fixture to reuse the same setup in every test. - // We use loadFixture to run this setup once, snapshot that state, - // and reset Hardhat Network to that snapshot in every test. - async function deployOneYearLockFixture() { - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const ONE_GWEI = 1_000_000_000; - - const lockedAmount = ONE_GWEI; - const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; - - // Contracts are deployed using the first signer/account by default - const [owner, otherAccount] = await ethers.getSigners(); - - const Lock = await ethers.getContractFactory("Lock"); - const lock = await Lock.deploy(unlockTime, { value: lockedAmount }); - - return { lock, unlockTime, lockedAmount, owner, otherAccount }; - } - - describe("Deployment", function () { - it("Should set the right unlockTime", async function () { - const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.unlockTime()).to.equal(unlockTime); - }); - - it("Should set the right owner", async function () { - const { lock, owner } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.owner()).to.equal(owner.address); - }); - - it("Should receive and store the funds to lock", async function () { - const { lock, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - - expect(await ethers.provider.getBalance(lock.address)).to.equal( - lockedAmount - ); - }); - - it("Should fail if the unlockTime is not in the future", async function () { - // We don't use the fixture here because we want a different deployment - const latestTime = await time.latest(); - const Lock = await ethers.getContractFactory("Lock"); - await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith( - "Unlock time should be in the future" - ); - }); - }); - - describe("Withdrawals", function () { - describe("Validations", function () { - it("Should revert with the right error if called too soon", async function () { - const { lock } = await loadFixture(deployOneYearLockFixture); - - await expect(lock.withdraw()).to.be.revertedWith( - "You can't withdraw yet" - ); - }); - - it("Should revert with the right error if called from another account", async function () { - const { lock, unlockTime, otherAccount } = await loadFixture( - deployOneYearLockFixture - ); - - // We can increase the time in Hardhat Network - await time.increaseTo(unlockTime); - - // We use lock.connect() to send a transaction from another account - await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith( - "You aren't the owner" - ); - }); - - it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () { - const { lock, unlockTime } = await loadFixture( - deployOneYearLockFixture - ); - - // Transactions are sent using the first signer by default - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()).not.to.be.reverted; - }); - }); - - describe("Events", function () { - it("Should emit an event on withdrawals", async function () { - const { lock, unlockTime, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()) - .to.emit(lock, "Withdrawal") - .withArgs(lockedAmount, anyValue); // We accept any value as `when` arg - }); - }); - - describe("Transfers", function () { - it("Should transfer the funds to the owner", async function () { - const { lock, unlockTime, lockedAmount, owner } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()).to.changeEtherBalances( - [owner, lock], - [lockedAmount, -lockedAmount] - ); - }); - }); - }); -}); diff --git a/test/RecoverToken.js b/test/RecoverToken.js new file mode 100644 index 0000000..59763a6 --- /dev/null +++ b/test/RecoverToken.js @@ -0,0 +1,55 @@ +const { StakeFXVaultV2Address, WFXAddress, FXAddress } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("RecoverToken", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const owner = signers.slice(-1)[0]; + const notOwners = signers.slice(0, -1); + return { stFX, owner, notOwners }; + } + it("Owner (other token address)", async () => { + const { stFX, owner, notOwners } = await loadContractFixture(); + const amount = ethers.utils.parseEther("1"); + + for (const notOwner of notOwners) { + await stFX.connect(owner).recoverToken(WFXAddress, amount, notOwner.address); + } + }) + it("Owner (FX token address)", async () => { + const { stFX, owner, notOwners } = await loadContractFixture(); + const amount = ethers.utils.parseEther("1"); + + for (const notOwner of notOwners) { + await stFX.connect(owner).recoverToken(FXAddress, amount, notOwner.address); + } + }) + it("Not owner (other token address)", async () => { + const { stFX, notOwners } = await loadContractFixture(); + const amount = ethers.utils.parseEther("1"); + + for (let i = 0; i < notOwners.length; i++) { + let notOwner = notOwners[i]; + let value = notOwners.length - i - 1; + await expect( + stFX.connect(notOwner).callStatic.recoverToken(WFXAddress, amount, notOwners[value].address) + ).rejectedWith(Error, `AccessControl`); + } + }) + it("Not owner (FX token address)", async () => { + const { stFX, notOwners } = await loadContractFixture(); + const amount = ethers.utils.parseEther("1"); + + for (let i = 0; i < notOwners.length; i++) { + let notOwner = notOwners[i]; + let value = notOwners.length - i - 1; + await expect( + stFX.connect(notOwner).callStatic.recoverToken(FXAddress, amount, notOwners[value].address) + ).rejectedWith(Error, `AccessControl`); + } + }) +}); \ No newline at end of file diff --git a/test/RemoveValidator.js b/test/RemoveValidator.js new file mode 100644 index 0000000..3cc7c21 --- /dev/null +++ b/test/RemoveValidator.js @@ -0,0 +1,28 @@ +const { StakeFXVaultV2Address, validator2 } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("RemoveValidator", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser } = await loadContractFixture(); + await stFX.connect(authorizedUser).removeValidator(); + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthUser of notAuthorizedUsers) { + await expect( + stFX.connect(notAuthUser).callStatic.removeValidator() + ).rejectedWith(Error, `AccessControl`); + } + }); +}); \ No newline at end of file diff --git a/test/SendVestedFx.js b/test/SendVestedFx.js new file mode 100644 index 0000000..9340c3b --- /dev/null +++ b/test/SendVestedFx.js @@ -0,0 +1,31 @@ +const { StakeFXVaultV2Address } = require("../utils/constant"); +const { ethers } = require("hardhat"); +const { expect } = require("chai"); + +describe("SendVestedFX", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + return { stFX, signers }; + } + // it("Is vested contract address", async()=>{ + // const {stFX} = await loadContractFixture() + // const stakeAmount = ethers.utils.parseEther("1") + // const deployedVestedContractAddress = "0x61f4139abbEB9Af11B9c07FBa862E48e823294CA" + // await stFX.connect(deployedVestedContractAddress).callStatic.sendVestedFX(stakeAmount) + // }) + it("Is not vested contract address", async () => { + const { stFX, signers } = await loadContractFixture(); + const stakeAmount = ethers.utils.parseEther("1"); + + for (const addr of signers) { + await expect(stFX.connect(addr).callStatic.sendVestedFX(stakeAmount)).rejectedWith( + Error, + "Only VestedFX can call" + ); + } + }); +}); \ No newline at end of file diff --git a/test/UpdateConfigs.js b/test/UpdateConfigs.js new file mode 100644 index 0000000..18debca --- /dev/null +++ b/test/UpdateConfigs.js @@ -0,0 +1,28 @@ +const { StakeFXVaultV2Address } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("UpdateConfigs", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser } = await loadContractFixture(); + await stFX.connect(authorizedUser).callStatic.updateConfigs(1, 1, 1, 1); + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthUser of notAuthorizedUsers) { + await expect( + stFX.connect(notAuthUser).callStatic.updateConfigs(1, 1, 1, 1) + ).rejectedWith(Error, `AccessControl`); + } + }); +}); \ No newline at end of file diff --git a/test/UpdateDistributor.js b/test/UpdateDistributor.js new file mode 100644 index 0000000..a5a416d --- /dev/null +++ b/test/UpdateDistributor.js @@ -0,0 +1,37 @@ +const { StakeFXVaultV2Address } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("UpdateDistributor", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthorizedUser of notAuthorizedUsers) { + await stFX + .connect(authorizedUser) + .callStatic.updateDistributor(notAuthorizedUser.address); + } + }) + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (let i = 0; i < notAuthorizedUsers.length; i++) { + let notAuthUser = notAuthorizedUsers[i]; + let value = notAuthorizedUsers.length - i - 1; + await expect( + stFX + .connect(notAuthUser) + .callStatic.updateDistributor(notAuthorizedUsers[value].address) + ).rejectedWith(Error, `AccessControl`); + } + }) +}); \ No newline at end of file diff --git a/test/UpdateFeeTreasury.js b/test/UpdateFeeTreasury.js new file mode 100644 index 0000000..129bea5 --- /dev/null +++ b/test/UpdateFeeTreasury.js @@ -0,0 +1,38 @@ +const { StakeFXVaultV2Address } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("UpdateFeeTreasury", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser, notAuthorizedUsers } = + await loadContractFixture(); + + for (const notAuthorizedUser of notAuthorizedUsers) { + await stFX + .connect(authorizedUser) + .callStatic.updateFeeTreasury(notAuthorizedUser.address); + } + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (let i = 0; i < notAuthorizedUsers.length; i++) { + let notAuthUser = notAuthorizedUsers[i]; + let value = notAuthorizedUsers.length - i - 1; + await expect( + stFX + .connect(notAuthUser) + .callStatic.updateFeeTreasury(notAuthorizedUsers[value].address) + ).rejectedWith(Error, `AccessControl`); + } + }); +}); \ No newline at end of file diff --git a/test/UpdateFees.js b/test/UpdateFees.js new file mode 100644 index 0000000..3bea825 --- /dev/null +++ b/test/UpdateFees.js @@ -0,0 +1,30 @@ +const { StakeFXVaultV2Address } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("UpdateFees", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser } = await loadContractFixture(); + await stFX.connect(authorizedUser).callStatic.updateFees(1, 1, 1); + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthUser of notAuthorizedUsers) { + await expect( + stFX.connect(notAuthUser).callStatic.updateFees(1, 1, 1) + ).rejectedWith(Error, `AccessControl`); + } + }); + + +}); \ No newline at end of file diff --git a/test/UpdateValidator.js b/test/UpdateValidator.js new file mode 100644 index 0000000..efba60d --- /dev/null +++ b/test/UpdateValidator.js @@ -0,0 +1,28 @@ +const { StakeFXVaultV2Address, validator2 } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("UpdateValidator", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser } = await loadContractFixture(); + await stFX.connect(authorizedUser).updateValidator(1,1); + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthUser of notAuthorizedUsers) { + await expect( + stFX.connect(notAuthUser).callStatic.updateValidator(1,1) + ).rejectedWith(Error, `AccessControl`); + } + }); +}); \ No newline at end of file diff --git a/test/UpdateVestedFx.js b/test/UpdateVestedFx.js new file mode 100644 index 0000000..46e32ce --- /dev/null +++ b/test/UpdateVestedFx.js @@ -0,0 +1,33 @@ +const { StakeFXVaultV2Address } = require("../utils/constant"); +const { expect } = require("chai"); + +describe("UpdateVestedFX", () => { + async function loadContractFixture() { + const stFX = await ethers.getContractAt( + "StakeFXVaultV2", + StakeFXVaultV2Address + ); + const signers = await ethers.getSigners(); + const authorizedUser = signers.slice(-1)[0]; + const notAuthorizedUsers = signers.slice(0, -1); + return { stFX, authorizedUser, notAuthorizedUsers }; + } + it("Authorized user", async () => { + const { stFX, authorizedUser, notAuthorizedUsers } = await loadContractFixture(); + + for (const notAuthorizedUser of notAuthorizedUsers) { + await stFX.connect(authorizedUser).callStatic.updateVestedFX(notAuthorizedUser.address); + } + }); + it("Not authorized user", async () => { + const { stFX, notAuthorizedUsers } = await loadContractFixture(); + + for (let i = 0; i < notAuthorizedUsers.length; i++) { + let notAuthUser = notAuthorizedUsers[i]; + let value = notAuthorizedUsers.length - i - 1; + await expect( + stFX.connect(notAuthUser).callStatic.updateVestedFX(notAuthorizedUsers[value].address) + ).rejectedWith(Error, `AccessControl`); + } + }) +}); \ No newline at end of file diff --git a/test/test.js b/test/test.js index fb5cef7..47b5210 100644 --- a/test/test.js +++ b/test/test.js @@ -67,12 +67,12 @@ async function main() { const multicallContract = await ethers.getContractAt("MultiCall", multicall); const allDelegation = await multicallContract.getAllValidatorDelegation(); - console.log(tokensToEther(allDelegation[0][2].toString())) - console.log(tokensToEther(allDelegation[1][2].toString())) - console.log(tokensToEther(allDelegation[2][2].toString())) - console.log(tokensToEther(allDelegation[3][2].toString())) - console.log(tokensToEther(allDelegation[4][2].toString())) - console.log(tokensToEther(allDelegation[5][2].toString())) + console.log("0) "+tokensToEther(allDelegation[0][2].toString())) + console.log("1) "+tokensToEther(allDelegation[1][2].toString())) + console.log("2) "+tokensToEther(allDelegation[2][2].toString())) + console.log("3) "+tokensToEther(allDelegation[3][2].toString())) + console.log("4) "+tokensToEther(allDelegation[4][2].toString())) + console.log("5) "+tokensToEther(allDelegation[5][2].toString())) } main() diff --git a/test/verify.json b/test/verify.json index 75d9fd0..0885d45 100644 --- a/test/verify.json +++ b/test/verify.json @@ -1,6 +1,12 @@ { "language": "Solidity", "sources": { + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../utils/StringsUpgradeable.sol\";\nimport \"../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {\n function __AccessControl_init() internal onlyInitializing {\n }\n\n function __AccessControl_init_unchained() internal onlyInitializing {\n }\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n StringsUpgradeable.toHexString(account),\n \" is missing role \",\n StringsUpgradeable.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\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[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\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" }, @@ -10,6 +16,9 @@ "@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/interfaces/IERC4626Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20Upgradeable.sol\";\nimport \"../token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n *\n * _Available since v4.7._\n */\ninterface IERC4626Upgradeable is IERC20Upgradeable, IERC20MetadataUpgradeable {\n event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n event Withdraw(\n address indexed sender,\n address indexed receiver,\n address indexed owner,\n uint256 assets,\n uint256 shares\n );\n\n /**\n * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n *\n * - MUST be an ERC-20 token contract.\n * - MUST NOT revert.\n */\n function asset() external view returns (address assetTokenAddress);\n\n /**\n * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n *\n * - SHOULD include any compounding that occurs from yield.\n * - MUST be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT revert.\n */\n function totalAssets() external view returns (uint256 totalManagedAssets);\n\n /**\n * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n * through a deposit call.\n *\n * - MUST return a limited value if receiver is subject to some deposit limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n * - MUST NOT revert.\n */\n function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n * in the same transaction.\n * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n * deposit would be accepted, regardless if the user has enough tokens approved, etc.\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n */\n function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n *\n * - MUST emit the Deposit event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * deposit execution, and are accounted for during deposit.\n * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n * approving enough underlying tokens to the Vault contract, etc).\n *\n * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n */\n function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n /**\n * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n * - MUST return a limited value if receiver is subject to some mint limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n * - MUST NOT revert.\n */\n function maxMint(address receiver) external view returns (uint256 maxShares);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n * same transaction.\n * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n * would be accepted, regardless if the user has enough tokens approved, etc.\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by minting.\n */\n function previewMint(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n *\n * - MUST emit the Deposit event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n * execution, and are accounted for during mint.\n * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n * approving enough underlying tokens to the Vault contract, etc).\n *\n * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n */\n function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n * Vault, through a withdraw call.\n *\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n * - MUST NOT revert.\n */\n function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n * given current on-chain conditions.\n *\n * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n * called\n * in the same transaction.\n * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n * the withdrawal would be accepted, regardless if the user has enough shares, etc.\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n */\n function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n *\n * - MUST emit the Withdraw event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * withdraw execution, and are accounted for during withdraw.\n * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n * not having enough shares, etc).\n *\n * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n * Those methods should be performed separately.\n */\n function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n /**\n * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n * through a redeem call.\n *\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n * - MUST NOT revert.\n */\n function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n * given current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n * same transaction.\n * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n * redemption would be accepted, regardless if the user has enough shares, etc.\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n */\n function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n *\n * - MUST emit the Withdraw event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * redeem execution, and are accounted for during redeem.\n * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n * not having enough shares, etc).\n *\n * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n * Those methods should be performed separately.\n */\n function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\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" }, @@ -22,9 +31,21 @@ "@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/ERC4626Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../utils/SafeERC20Upgradeable.sol\";\nimport \"../../../interfaces/IERC4626Upgradeable.sol\";\nimport \"../../../utils/math/MathUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC4626 \"Tokenized Vault Standard\" as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[EIP-4626].\n *\n * This extension allows the minting and burning of \"shares\" (represented using the ERC20 inheritance) in exchange for\n * underlying \"assets\" through standardized {deposit}, {mint}, {redeem} and {burn} workflows. This contract extends\n * the ERC20 standard. Any additional extensions included along it would affect the \"shares\" token represented by this\n * contract and not the \"assets\" token which is an independent contract.\n *\n * [CAUTION]\n * ====\n * In empty (or nearly empty) ERC-4626 vaults, deposits are at high risk of being stolen through frontrunning\n * with a \"donation\" to the vault that inflates the price of a share. This is variously known as a donation or inflation\n * attack and is essentially a problem of slippage. Vault deployers can protect against this attack by making an initial\n * deposit of a non-trivial amount of the asset, such that price manipulation becomes infeasible. Withdrawals may\n * similarly be affected by slippage. Users can protect against this attack as well as unexpected slippage in general by\n * verifying the amount received is as expected, using a wrapper that performs these checks such as\n * https://github.com/fei-protocol/ERC4626#erc4626router-and-base[ERC4626Router].\n *\n * Since v4.9, this implementation uses virtual assets and shares to mitigate that risk. The `_decimalsOffset()`\n * corresponds to an offset in the decimal representation between the underlying asset's decimals and the vault\n * decimals. This offset also determines the rate of virtual shares to virtual assets in the vault, which itself\n * determines the initial exchange rate. While not fully preventing the attack, analysis shows that the default offset\n * (0) makes it non-profitable, as a result of the value being captured by the virtual shares (out of the attacker's\n * donation) matching the attacker's expected gains. With a larger offset, the attack becomes orders of magnitude more\n * expensive than it is profitable. More details about the underlying math can be found\n * xref:erc4626.adoc#inflation-attack[here].\n *\n * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued\n * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets\n * will cause the first user to exit to experience reduced losses in detriment to the last users that will experience\n * bigger losses. Developers willing to revert back to the pre-v4.9 behavior just need to override the\n * `_convertToShares` and `_convertToAssets` functions.\n *\n * To learn more, check out our xref:ROOT:erc4626.adoc[ERC-4626 guide].\n * ====\n *\n * _Available since v4.7._\n */\nabstract contract ERC4626Upgradeable is Initializable, ERC20Upgradeable, IERC4626Upgradeable {\n using MathUpgradeable for uint256;\n\n IERC20Upgradeable private _asset;\n uint8 private _underlyingDecimals;\n\n /**\n * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).\n */\n function __ERC4626_init(IERC20Upgradeable asset_) internal onlyInitializing {\n __ERC4626_init_unchained(asset_);\n }\n\n function __ERC4626_init_unchained(IERC20Upgradeable asset_) internal onlyInitializing {\n (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_);\n _underlyingDecimals = success ? assetDecimals : 18;\n _asset = asset_;\n }\n\n /**\n * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way.\n */\n function _tryGetAssetDecimals(IERC20Upgradeable asset_) private view returns (bool, uint8) {\n (bool success, bytes memory encodedDecimals) = address(asset_).staticcall(\n abi.encodeWithSelector(IERC20MetadataUpgradeable.decimals.selector)\n );\n if (success && encodedDecimals.length >= 32) {\n uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));\n if (returnedDecimals <= type(uint8).max) {\n return (true, uint8(returnedDecimals));\n }\n }\n return (false, 0);\n }\n\n /**\n * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This\n * \"original\" value is cached during construction of the vault contract. If this read operation fails (e.g., the\n * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals.\n *\n * See {IERC20Metadata-decimals}.\n */\n function decimals() public view virtual override(IERC20MetadataUpgradeable, ERC20Upgradeable) returns (uint8) {\n return _underlyingDecimals + _decimalsOffset();\n }\n\n /** @dev See {IERC4626-asset}. */\n function asset() public view virtual override returns (address) {\n return address(_asset);\n }\n\n /** @dev See {IERC4626-totalAssets}. */\n function totalAssets() public view virtual override returns (uint256) {\n return _asset.balanceOf(address(this));\n }\n\n /** @dev See {IERC4626-convertToShares}. */\n function convertToShares(uint256 assets) public view virtual override returns (uint256) {\n return _convertToShares(assets, MathUpgradeable.Rounding.Down);\n }\n\n /** @dev See {IERC4626-convertToAssets}. */\n function convertToAssets(uint256 shares) public view virtual override returns (uint256) {\n return _convertToAssets(shares, MathUpgradeable.Rounding.Down);\n }\n\n /** @dev See {IERC4626-maxDeposit}. */\n function maxDeposit(address) public view virtual override returns (uint256) {\n return type(uint256).max;\n }\n\n /** @dev See {IERC4626-maxMint}. */\n function maxMint(address) public view virtual override returns (uint256) {\n return type(uint256).max;\n }\n\n /** @dev See {IERC4626-maxWithdraw}. */\n function maxWithdraw(address owner) public view virtual override returns (uint256) {\n return _convertToAssets(balanceOf(owner), MathUpgradeable.Rounding.Down);\n }\n\n /** @dev See {IERC4626-maxRedeem}. */\n function maxRedeem(address owner) public view virtual override returns (uint256) {\n return balanceOf(owner);\n }\n\n /** @dev See {IERC4626-previewDeposit}. */\n function previewDeposit(uint256 assets) public view virtual override returns (uint256) {\n return _convertToShares(assets, MathUpgradeable.Rounding.Down);\n }\n\n /** @dev See {IERC4626-previewMint}. */\n function previewMint(uint256 shares) public view virtual override returns (uint256) {\n return _convertToAssets(shares, MathUpgradeable.Rounding.Up);\n }\n\n /** @dev See {IERC4626-previewWithdraw}. */\n function previewWithdraw(uint256 assets) public view virtual override returns (uint256) {\n return _convertToShares(assets, MathUpgradeable.Rounding.Up);\n }\n\n /** @dev See {IERC4626-previewRedeem}. */\n function previewRedeem(uint256 shares) public view virtual override returns (uint256) {\n return _convertToAssets(shares, MathUpgradeable.Rounding.Down);\n }\n\n /** @dev See {IERC4626-deposit}. */\n function deposit(uint256 assets, address receiver) public virtual override returns (uint256) {\n require(assets <= maxDeposit(receiver), \"ERC4626: deposit more than max\");\n\n uint256 shares = previewDeposit(assets);\n _deposit(_msgSender(), receiver, assets, shares);\n\n return shares;\n }\n\n /** @dev See {IERC4626-mint}.\n *\n * As opposed to {deposit}, minting is allowed even if the vault is in a state where the price of a share is zero.\n * In this case, the shares will be minted without requiring any assets to be deposited.\n */\n function mint(uint256 shares, address receiver) public virtual override returns (uint256) {\n require(shares <= maxMint(receiver), \"ERC4626: mint more than max\");\n\n uint256 assets = previewMint(shares);\n _deposit(_msgSender(), receiver, assets, shares);\n\n return assets;\n }\n\n /** @dev See {IERC4626-withdraw}. */\n function withdraw(uint256 assets, address receiver, address owner) public virtual override returns (uint256) {\n require(assets <= maxWithdraw(owner), \"ERC4626: withdraw more than max\");\n\n uint256 shares = previewWithdraw(assets);\n _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n return shares;\n }\n\n /** @dev See {IERC4626-redeem}. */\n function redeem(uint256 shares, address receiver, address owner) public virtual override returns (uint256) {\n require(shares <= maxRedeem(owner), \"ERC4626: redeem more than max\");\n\n uint256 assets = previewRedeem(shares);\n _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n return assets;\n }\n\n /**\n * @dev Internal conversion function (from assets to shares) with support for rounding direction.\n */\n function _convertToShares(uint256 assets, MathUpgradeable.Rounding rounding) internal view virtual returns (uint256) {\n return assets.mulDiv(totalSupply() + 10 ** _decimalsOffset(), totalAssets() + 1, rounding);\n }\n\n /**\n * @dev Internal conversion function (from shares to assets) with support for rounding direction.\n */\n function _convertToAssets(uint256 shares, MathUpgradeable.Rounding rounding) internal view virtual returns (uint256) {\n return shares.mulDiv(totalAssets() + 1, totalSupply() + 10 ** _decimalsOffset(), rounding);\n }\n\n /**\n * @dev Deposit/mint common workflow.\n */\n function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual {\n // If _asset is ERC777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the\n // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer,\n // calls the vault, which is assumed not malicious.\n //\n // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the\n // assets are transferred and before the shares are minted, which is a valid state.\n // slither-disable-next-line reentrancy-no-eth\n SafeERC20Upgradeable.safeTransferFrom(_asset, caller, address(this), assets);\n _mint(receiver, shares);\n\n emit Deposit(caller, receiver, assets, shares);\n }\n\n /**\n * @dev Withdraw/redeem common workflow.\n */\n function _withdraw(\n address caller,\n address receiver,\n address owner,\n uint256 assets,\n uint256 shares\n ) internal virtual {\n if (caller != owner) {\n _spendAllowance(owner, caller, shares);\n }\n\n // If _asset is ERC777, `transfer` can trigger a reentrancy AFTER the transfer happens through the\n // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer,\n // calls the vault, which is assumed not malicious.\n //\n // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the\n // shares are burned and after the assets are transferred, which is a valid state.\n _burn(owner, shares);\n SafeERC20Upgradeable.safeTransfer(_asset, receiver, assets);\n\n emit Withdraw(caller, receiver, owner, assets, shares);\n }\n\n function _decimalsOffset() internal view virtual returns (uint8) {\n return 0;\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/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" }, @@ -40,20 +61,68 @@ "@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/introspection/ERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\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/introspection/IERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMathUpgradeable {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\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-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\nimport \"./math/SignedMathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMathUpgradeable.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "contracts/common/Governable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {AccessControlUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\n\nabstract contract Governable is AccessControlUpgradeable {\n bytes32 public constant OWNER_ROLE = bytes32(\"OWNER_ROLE\");\n bytes32 public constant GOVERNOR_ROLE = bytes32(\"GOVERNOR_ROLE\");\n bytes32 public constant OPERATOR_ROLE = bytes32(\"OPERATOR_ROLE\"); // only contract address\n\n function __Governable_init(address _owner, address _governor) internal {\n // Assign roles to the sender.\n _grantRole(OWNER_ROLE, _owner);\n _grantRole(GOVERNOR_ROLE, _governor);\n\n // Set OWNER_ROLE as the admin of all roles.\n _setRoleAdmin(OWNER_ROLE, OWNER_ROLE);\n _setRoleAdmin(GOVERNOR_ROLE, OWNER_ROLE);\n _setRoleAdmin(OPERATOR_ROLE, OWNER_ROLE);\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}" + }, + "contracts/imp/PrecompileStaking.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.10;\n\nimport {Encode} from \"../libraries/Encode.sol\";\nimport {Decode} from \"../libraries/Decode.sol\";\nimport {IPrecompileStaking} from \"../interfaces/IPrecompileStaking.sol\";\n\n/**\n * @title PrecompileStaking\n *\n * @dev Interface to interact to network precompile staking contract functions.\n */\nabstract contract PrecompileStaking {\n\n address private constant _stakingAddress = address(0x0000000000000000000000000000000000001003);\n\n /**************************************** Precompile Staking Internal Functions ****************************************/\n\n function _delegate(string memory _val, uint256 _amount) internal returns (uint256, uint256) {\n (bool result, bytes memory data) = _stakingAddress.call{value: _amount}(Encode.delegate(_val));\n Decode.ok(result, data, \"delegate failed\");\n\n return Decode.delegate(data);\n }\n\n function _undelegate(string memory _val, uint256 _shares) internal returns (uint256, uint256, uint256) {\n (bool result, bytes memory data) = _stakingAddress.call(Encode.undelegate(_val, _shares));\n Decode.ok(result, data, \"undelegate failed\");\n\n return Decode.undelegate(data);\n }\n\n function _redelegate(string memory _valSrc, string memory _valDst, uint256 _shares) internal returns (uint256, uint256, uint256) {\n (bool result, bytes memory data) = _stakingAddress.call(Encode.redelegate(_valSrc, _valDst, _shares));\n Decode.ok(result, data, \"redelegate failed\");\n\n return Decode.redelegate(data);\n }\n\n function _delegateV2(string memory _val, uint256 _amount) internal returns (bool _result) {\n require(address(this).balance >= _amount, \"insufficient balance\");\n return IPrecompileStaking(_stakingAddress).delegateV2(_val, _amount);\n }\n\n function _undelegateV2(string memory _val, uint256 _amount) internal returns (bool _result) {\n return IPrecompileStaking(_stakingAddress).undelegateV2(_val,_amount);\n }\n\n function _redelegateV2(string memory _valSrc, string memory _valDst, uint256 _amount) internal returns (bool _result) {\n return IPrecompileStaking(_stakingAddress).redelegateV2(_valSrc, _valDst, _amount);\n }\n\n function _withdraw(string memory _val) internal returns (uint256) {\n (bool result, bytes memory data) = _stakingAddress.call(Encode.withdraw(_val));\n Decode.ok(result, data, \"withdraw failed\");\n\n return Decode.withdraw(data);\n }\n\n function _transferShares(string memory _val, address _to, uint256 _shares) internal returns (uint256, uint256) {\n (bool result, bytes memory data) = _stakingAddress.call(Encode.transferShares(_val, _to, _shares));\n Decode.ok(result, data, \"transferShares failed\");\n\n return Decode.transferShares(data);\n }\n\n function _transferFromShares(string memory _val, address _from, address _to, uint256 _shares) internal returns (uint256, uint256) {\n (bool result, bytes memory data) = _stakingAddress.call(Encode.transferFromShares(_val, _from, _to, _shares));\n Decode.ok(result, data, \"transferFromShares failed\");\n\n return Decode.transferFromShares(data);\n }\n\n function _delegation(string memory _val, address _del) internal view returns (uint256, uint256) {\n (bool result, bytes memory data) = _stakingAddress.staticcall(Encode.delegation(_val, _del));\n Decode.ok(result, data, \"delegation failed\");\n\n return Decode.delegation(data);\n }\n\n function _delegationRewards(string memory _val, address _del) internal view returns (uint256) {\n (bool result, bytes memory data) = _stakingAddress.staticcall(Encode.delegationRewards(_val, _del));\n Decode.ok(result, data, \"delegationRewards failed\");\n\n return Decode.delegationRewards(data);\n }\n\n function _allowanceShares(string memory _val, address _owner, address _spender) internal view returns (uint256) {\n (bool result, bytes memory data) = _stakingAddress.staticcall(Encode.allowanceShares(_val, _owner, _spender));\n Decode.ok(result, data, \"allowanceShares failed\");\n\n return Decode.allowanceShares(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[49] private __gap;\n}" + }, + "contracts/interfaces/IPrecompileStaking.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.10;\n\n/**\n * @title IPrecompileStaking\n *\n * @dev Interface to interact to network precompile staking contract functions.\n */\ninterface IPrecompileStaking {\n\n function delegate(string memory _val) external payable returns (uint256, uint256);\n\n function undelegate(string memory _val, uint256 _shares) external returns (uint256, uint256, uint256);\n\n function withdraw(string memory _val) external returns (uint256);\n\n function transferFromShares(string memory _val, address _from, address _to, uint256 _shares) external returns (uint256, uint256);\n\n function delegation(string memory _val, address _del) external view returns (uint256, uint256);\n\n function delegationRewards(string memory _val, address _del) external view returns (uint256);\n\n function delegateV2(\n string memory _val,\n uint256 _amount\n ) external payable returns (bool _result);\n\n function undelegateV2(\n string memory _val,\n uint256 _amount\n ) external returns (bool _result);\n\n function redelegateV2(\n string memory _valSrc,\n string memory _valDst,\n uint256 _amount\n ) external returns (bool _result);\n}" + }, + "contracts/interfaces/IRewardDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\ninterface IRewardDistributor {\n function rewardToken() external view returns (address);\n function tokensPerInterval() external view returns (uint256);\n function pendingRewards() external view returns (uint256);\n function distribute() external returns (uint256);\n}" + }, "contracts/interfaces/IStakeFXVault.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\npragma solidity ^0.8.0;\n\ninterface IStakeFXVault {\n\n function sendVestedFX(uint256 safeAmount) external;\n\n function updateRewards() external;\n\n function getValLength() external view returns (uint256);\n\n function getValInfo(uint256 index) external view returns (uint256, string memory);\n}\n" + "content": "// SPDX-License-Identifier: Apache-2.0\n\npragma solidity ^0.8.0;\n\ninterface IStakeFXVault {\n\n function sendVestedFX(uint256 safeAmount) external;\n\n function updateRewards() external;\n\n function getValLength() external view returns (uint256);\n\n function getValInfo(uint256 index) external view returns (uint256, string memory);\n\n function stake(uint256 amount, bool native) external payable;\n\n function unstake(uint256 amount) external;\n\n function entrustDelegatedShare(string memory val, uint256 amount) external;\n\n function compound() external;\n\n function claim(address receiver) external returns (uint256);\n}\n" }, "contracts/interfaces/IVestedFX.sol": { "content": "// SPDX-License-Identifier: Apache-2.0\n\npragma solidity ^0.8.0;\n\ninterface IVestedFX {\n \n struct VestingSchedule {\n uint64 startTime;\n uint64 endTime;\n uint256 quantity;\n uint256 vestedQuantity;\n }\n\n function lockWithEndTime(address account, uint256 quantity, uint256 endTime) external;\n\n function getVestingSchedules(address account) external view returns (VestingSchedule[] memory);\n\n function accountEscrowedBalance(address account) external view returns (uint256);\n\n function accountVestedBalance(address account) external view returns (uint256);\n}" }, + "contracts/interfaces/IWFX.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\npragma solidity ^0.8.0;\n\ninterface IWFX {\n function deposit() external payable;\n\n function withdraw(address payable to, uint256 value) external;\n\n function transferFrom(address from, address to, uint256 amount) external;\n}" + }, + "contracts/libraries/Decode.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nlibrary Decode {\n function delegate(\n bytes memory data\n ) internal pure returns (uint256, uint256) {\n (uint256 shares, uint256 reward) = abi.decode(data, (uint256, uint256));\n return (shares, reward);\n }\n\n function undelegate(\n bytes memory data\n ) internal pure returns (uint256, uint256, uint256) {\n (uint256 amount, uint256 reward, uint256 endTime) = abi.decode(\n data,\n (uint256, uint256, uint256)\n );\n return (amount, reward, endTime);\n }\n\n function redelegate(bytes memory data) internal pure returns (uint256, uint256, uint256) {\n (uint256 _amount, uint256 _reward, uint256 _completionTime) = abi.decode(data, (uint256, uint256, uint256));\n return (_amount, _reward, _completionTime);\n }\n\n function delegateV2(\n bytes memory data\n ) internal pure returns (bool) {\n (bool _result) = abi.decode(data, (bool));\n return (_result);\n }\n\n function undelegateV2(\n bytes memory data\n ) internal pure returns (bool) {\n (bool _result) = abi.decode(\n data,\n (bool)\n );\n return (_result);\n }\n\n function redelegateV2(bytes memory data) internal pure returns (bool) {\n (bool _result) = abi.decode(data, (bool));\n return (_result);\n }\n\n function withdraw(bytes memory data) internal pure returns (uint256) {\n uint256 reward = abi.decode(data, (uint256));\n return reward;\n }\n\n function transferShares(bytes memory data) internal pure returns (uint256, uint256) {\n (uint256 token, uint256 reward) = abi.decode(data, (uint256, uint256));\n return (token, reward);\n }\n\n function transferFromShares(bytes memory data) internal pure returns (uint256, uint256) {\n (uint256 token, uint256 reward) = abi.decode(data, (uint256, uint256));\n return (token, reward);\n }\n\n function delegation(bytes memory data) internal pure returns (uint256, uint256) {\n (uint256 delegateShare, uint256 delegateAmount) = abi.decode(data, (uint256, uint256));\n return (delegateShare, delegateAmount);\n }\n\n function delegationRewards(bytes memory data) internal pure returns (uint256) {\n uint256 rewardAmount = abi.decode(data, (uint256));\n return rewardAmount;\n }\n\n function allowanceShares(bytes memory data) internal pure returns (uint256) {\n uint256 allowanceAmount = abi.decode(data, (uint256));\n return allowanceAmount;\n }\n\n function ok(\n bool _result,\n bytes memory _data,\n string memory _msg\n ) internal pure {\n if (!_result) {\n string memory errMsg = abi.decode(_data, (string));\n if (bytes(_msg).length < 1) {\n revert(errMsg);\n }\n revert(string(abi.encodePacked(_msg, \": \", errMsg)));\n }\n }\n}" + }, + "contracts/libraries/Encode.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nlibrary Encode {\n function delegate(\n string memory _validator\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"delegate(string)\", _validator);\n }\n\n function undelegate(\n string memory _validator,\n uint256 _shares\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"undelegate(string,uint256)\", _validator, _shares);\n }\n\n function redelegate(\n string memory _valSrc,\n string memory _valDst,\n uint256 _shares\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"redelegate(string,string,uint256)\", _valSrc, _valDst, _shares);\n }\n\n function delegateV2(\n string memory _validator,\n uint256 _amount\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"delegate(string, uint256)\", _validator, _amount);\n }\n\n function undelegateV2(\n string memory _validator,\n uint256 _amount\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"undelegate(string,uint256)\", _validator, _amount);\n }\n\n function redelegateV2(\n string memory _valSrc,\n string memory _valDst,\n uint256 _amount\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"redelegate(string,string,uint256)\", _valSrc, _valDst, _amount);\n }\n\n function withdraw(\n string memory _validator\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"withdraw(string)\", _validator);\n }\n\n function transferShares(\n string memory _validator,\n address _to,\n uint256 _shares\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"transferFromShares(string,address,uint256)\", _validator, _to, _shares);\n }\n\n function transferFromShares(\n string memory _validator,\n address _from,\n address _to,\n uint256 _shares\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"transferFromShares(string,address,address,uint256)\", _validator, _from, _to, _shares);\n }\n\n function delegation(\n string memory _validator,\n address _delegate\n ) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"delegation(string,address)\", _validator, _delegate);\n }\n\n function delegationRewards(\n string memory _validator, \n address _delegate) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"delegationRewards(string,address)\", _validator, _delegate);\n }\n\n function allowanceShares(\n string memory _validator, \n address _owner,\n address _spender) internal pure returns (bytes memory) {\n return abi.encodeWithSignature(\"allowanceShares(string,address,address)\", _validator, _owner, _spender);\n }\n}\n" + }, + "contracts/MultiCall.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\n\nimport {IStakeFXVault} from \"./interfaces/IStakeFXVault.sol\";\nimport {PrecompileStaking} from \"./imp/PrecompileStaking.sol\";\n\ncontract MultiCall is\n Initializable,\n UUPSUpgradeable,\n OwnableUpgradeable,\n PrecompileStaking\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n address stFX;\n\n struct ValidatorDelegationInfo {\n string validator;\n uint256 allocPoint;\n uint256 delegationAmount;\n uint256 delegationReward;\n }\n\n struct ValidatorUserDelegationInfo {\n string validator;\n uint256 delegationAmount;\n uint256 allowanceShares;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**************************************** Public/External View Functions ****************************************\n\n /**\n * @dev Get all validator delegation for stFX.\n */\n function getAllValidatorDelegation() external view returns (ValidatorDelegationInfo[] memory validatorDelegations) {\n uint256 validatorsLength = IStakeFXVault(stFX).getValLength();\n\n validatorDelegations = new ValidatorDelegationInfo[](validatorsLength);\n for (uint256 i = 0; i < validatorsLength; i++) {\n (uint256 valAllocPoint, string memory validatorAddress) = IStakeFXVault(stFX).getValInfo(i);\n (, uint256 delegationAmount) = _delegation(validatorAddress, stFX);\n uint256 delegationReward = _delegationRewards(validatorAddress, stFX);\n\n validatorDelegations[i] = ValidatorDelegationInfo({\n validator: validatorAddress,\n allocPoint: valAllocPoint,\n delegationAmount: delegationAmount,\n delegationReward: delegationReward\n });\n }\n }\n\n /**\n * @dev Get All Validator User Delegation\n */\n function getAllValidatorUserDelegation(address user) external view returns (ValidatorUserDelegationInfo[] memory validatorUserDelegations) {\n uint256 validatorsLength = IStakeFXVault(stFX).getValLength();\n\n validatorUserDelegations = new ValidatorUserDelegationInfo[](validatorsLength);\n for (uint256 i = 0; i < validatorsLength; i++) {\n (, string memory validatorAddress) = IStakeFXVault(stFX).getValInfo(i);\n \n (, uint256 delegationAmount) = _delegation(validatorAddress, user);\n uint256 allowanceShares = _allowanceShares(validatorAddress, user, stFX);\n\n validatorUserDelegations[i] = ValidatorUserDelegationInfo({\n validator: validatorAddress,\n delegationAmount: delegationAmount,\n allowanceShares: allowanceShares\n });\n }\n }\n\n /**************************************** Only Owner Functions ****************************************/\n\n function updateStFX(\n address _stFX\n ) external onlyOwner() {\n require(_stFX != address(0), \"Cannot 0 add\");\n require(_stFX != stFX, \"Cannot same add\");\n stFX = _stFX;\n }\n\n function recoverToken(\n address token,\n uint256 amount,\n address _recipient\n ) external onlyOwner() {\n require(_recipient != address(0), \"Send to zero address\");\n IERC20Upgradeable(token).safeTransfer(_recipient, amount);\n }\n\n function _authorizeUpgrade(\n address\n ) internal override onlyOwner() {} \n\n /**************************************************************\n * @dev Initialize the states\n *************************************************************/\n\n function initialize(address _stFX) public initializer {\n stFX = _stFX;\n __Ownable_init();\n __UUPSUpgradeable_init();\n }\n}" + }, + "contracts/RewardDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nimport {SafeMathUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol\";\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\n\nimport \"./interfaces/IRewardDistributor.sol\";\nimport \"./interfaces/IStakeFXVault.sol\";\nimport \"./common/Governable.sol\";\n\ncontract RewardDistributor is Initializable, UUPSUpgradeable, IRewardDistributor, ReentrancyGuardUpgradeable, Governable {\n using SafeMathUpgradeable for uint256;\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n address public override rewardToken;\n uint256 public override tokensPerInterval;\n uint256 public lastDistributionTime;\n address public rewardTracker;\n\n event Distribute(uint256 amount);\n event TokensPerIntervalChange(uint256 amount);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**************************************** Core Functions ****************************************/\n\n function distribute() external override returns (uint256) {\n require(msg.sender == rewardTracker, \"RewardDistributor: invalid msg.sender\");\n uint256 amount = pendingRewards();\n if (amount == 0) { return 0; }\n\n lastDistributionTime = block.timestamp;\n\n uint256 balance = IERC20Upgradeable(rewardToken).balanceOf(address(this));\n if (amount > balance) { amount = balance; }\n\n IERC20Upgradeable(rewardToken).safeTransfer(msg.sender, amount);\n\n emit Distribute(amount);\n return amount;\n }\n\n /**************************************** View Functions ****************************************/\n\n function pendingRewards() public view override returns (uint256) {\n if (block.timestamp == lastDistributionTime) {\n return 0;\n }\n\n uint256 timeDiff = block.timestamp.sub(lastDistributionTime);\n return tokensPerInterval.mul(timeDiff);\n }\n\n /**************************************** Only Admin/Governor Functions ****************************************/\n\n function updateLastDistributionTime() external onlyRole(GOVERNOR_ROLE) {\n lastDistributionTime = block.timestamp;\n }\n\n function setTokensPerInterval(uint256 _amount) external onlyRole(GOVERNOR_ROLE) {\n require(lastDistributionTime != 0, \"RewardDistributor: invalid lastDistributionTime\");\n IStakeFXVault(rewardTracker).updateRewards();\n tokensPerInterval = _amount;\n emit TokensPerIntervalChange(_amount);\n }\n\n\n\n /**************************************** Only Owner Functions ****************************************/\n\n /**\n * @dev Need to make sure all rewardTracker contracts fully migrate rewardToken to new rewardToken after update this contract rewardToken address\n */\n function updateRewardToken(address _rewardToken) external onlyRole(OWNER_ROLE) {\n rewardToken = _rewardToken;\n }\n\n function recoverToken(\n address token,\n uint256 amount,\n address _recipient\n ) external onlyRole(OWNER_ROLE) {\n require(_recipient != address(0), \"Send to zero address\");\n IERC20Upgradeable(token).safeTransfer(_recipient, amount);\n }\n\n function _authorizeUpgrade(\n address\n ) internal override onlyRole(OWNER_ROLE) {} \n\n /**************************************************************\n * @dev Initialize the states\n *************************************************************/ \n function initialize(\n address _rewardToken, address _rewardTracker, address _owner, address _governor\n ) public initializer {\n rewardToken = _rewardToken;\n rewardTracker = _rewardTracker;\n \n __Governable_init(_owner, _governor);\n __UUPSUpgradeable_init();\n }\n}" + }, + "contracts/StakeFXVaultV3.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nimport {IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport {MathUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\nimport {IVestedFX} from \"./interfaces/IVestedFX.sol\";\nimport {IRewardDistributor} from \"./interfaces/IRewardDistributor.sol\";\nimport {IWFX} from \"./interfaces/IWFX.sol\";\nimport {BaseVault} from \"./vaults/BaseVault.sol\";\nimport {PrecompileStaking} from \"./imp/PrecompileStaking.sol\";\n\ncontract StakeFXVaultV3 is\n Initializable,\n UUPSUpgradeable,\n PrecompileStaking,\n ReentrancyGuardUpgradeable,\n BaseVault\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using MathUpgradeable for uint256;\n\n uint256 internal constant BIPS_DIVISOR = 10000;\n uint256 internal constant PRECISION = 1e30;\n // address constant WFX = 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; // WFX mainnet: 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; WFX testnet: 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19\n\n uint256 public pendingFxReward; // FX delegation rewards inside the contract pending for compound\n uint256 public feeOnReward; // Compound reward protocol fee\n uint256 public feeOnCompounder; // Compound reward compounder fee\n uint256 public feeOnWithdrawal; // Withdrawal fee\n address public vestedFX; // Contract that stored user's withdrawal info\n address public feeTreasury; // Contract that keep compound reward fee\n address public distributor; // Reward token distributor\n\n uint256 private MIN_COMPOUND_AMOUNT; // Minimum reward amount to compound when stake happen\n uint256 private CAP_STAKE_FX_TARGET; // Cap amount of stFX\n uint256 private STAKE_FX_TARGET; // Target stake amount to do whole validator list delegate(Deprecated)\n uint256 private UNSTAKE_FX_TARGET; // Target unstake amount to split undelegate(Deprecated)\n \n VaultInfo public vaultInfo; // Vault Info\n mapping(uint256 => ValInfo) public valInfo; // Validator info\n mapping(address => UserInfo) public userInfo; // User info\n mapping(string => bool) public addedValidator; // True if validator is added\n\n address constant WFX = 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19; // WFX mainnet: 0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd; WFX testnet: 0x3452e23F9c4cC62c70B7ADAd699B264AF3549C19\n\n struct VaultInfo {\n uint256 stakeId;\n uint256 unstakeId;\n uint256 length;\n uint256 totalAllocPoint;\n uint256 cumulativeRewardPerToken;\n }\n\n struct ValInfo {\n uint256 allocPoint;\n string validator;\n }\n\n struct UserInfo {\n uint256 claimableReward;\n uint256 previousCumulatedRewardPerToken;\n }\n\n event Stake(address indexed user, uint256 amount, uint256 shares);\n event Unstake(address indexed user, uint256 amount, uint256 shares);\n event Compound(address indexed user, uint256 compoundAmount);\n event Claim(address receiver, uint256 amount);\n event ValidatorAdded(string val, uint256 newAllocPoint);\n event ValidatorRemoved(string val);\n event ValidatorUpdated(string val, uint256 newAllocPoint);\n event VestedFXChanged(address newAddress);\n event FeeTreasuryChanged(address newAddress);\n event DistributorChanged(address newAddress);\n event ValidatorRedelegated(string srcVal, string dstVal, uint256 sharesAmount, uint256 redelegatedShares); // last 2 arguments changed to FxAmount in staking V2\n\n receive() external payable {}\n\n modifier onlyVestedFX() {\n require(msg.sender == vestedFX, \"Only VestedFX can call\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /****************************************** Core External Functions ******************************************/\n /**\n * @notice user stake FX/WFX to this contract\n * @param amount stake amount\n * @param native stake FX or WFX token\n */\n function stake(uint256 amount, bool native) external payable nonReentrant whenNotPaused {\n require(amount > 0, \"Stake: 0 amount\");\n require(msg.value == (native == true ? amount : 0), \"!valid\");\n require(amount + totalAssets() <= CAP_STAKE_FX_TARGET, \"Stake: > Cap\");\n\n // Skip check delegation reward to save gas\n _compound();\n _claim(msg.sender, msg.sender);\n \n if(native == false) {\n IWFX(WFX).transferFrom(msg.sender, address(this), amount); \n IWFX(WFX).withdraw(payable(address(this)), amount);\n }\n\n uint256 shares = previewDeposit(amount);\n _mint(msg.sender, shares);\n\n _stake(amount);\n\n emit Stake(msg.sender, amount, shares);\n }\n\n /**\n * @notice user unstake(request undelegate FX)\n * @param amount User's fx-LP receipt tokens\n */\n function unstake(uint256 amount) external nonReentrant whenNotPaused {\n require(amount > 0, \"Unstake: 0 amount\");\n uint256 sharesBalance = balanceOf(msg.sender);\n require(sharesBalance >= amount, \"Amount > stake\");\n\n _compound();\n _claim(msg.sender, msg.sender);\n\n uint256 undelegateAmount = previewRedeem(amount);\n uint256 undelegateAmountAfterFee = undelegateAmount * (BIPS_DIVISOR - feeOnWithdrawal) / BIPS_DIVISOR;\n\n _burn(msg.sender, amount);\n if (undelegateAmountAfterFee > 0) {\n _unstake(undelegateAmountAfterFee);\n }\n \n emit Unstake(msg.sender, undelegateAmountAfterFee, amount);\n }\n\n /**\n * @notice transfer user delegation shares to this contract\n * @param val validator address\n * @param amount Amount of user's delegate shares transferred to this contract\n */\n function entrustDelegatedShare(string memory val, uint256 amount) external nonReentrant whenNotPaused {\n require(amount > 0, \"Entrust: 0 share\");\n\n (uint256 sharesAmount, uint256 delegationAmount) = _delegation(val, msg.sender);\n require(sharesAmount >= amount, \"Not enough share\");\n\n _compound();\n _claim(msg.sender, msg.sender);\n \n uint256 totalAsset = totalAssets();\n uint256 estimateDelegateAmount = amount / sharesAmount * delegationAmount;\n require(estimateDelegateAmount + totalAsset <= CAP_STAKE_FX_TARGET, \"Stake: > Cap\");\n\n uint256 supply = totalSupply();\n (uint256 fxAmountToTransfer, uint256 returnReward) = _transferFromShares(val, msg.sender, address(this), amount);\n\n pendingFxReward += returnReward;\n\n uint256 shares = (fxAmountToTransfer == 0 || supply == 0)\n ? _initialConvertToShares(fxAmountToTransfer, MathUpgradeable.Rounding.Down)\n : fxAmountToTransfer.mulDiv(supply, totalAsset, MathUpgradeable.Rounding.Down);\n\n _mint(msg.sender, shares);\n\n emit Stake(msg.sender, fxAmountToTransfer, shares); \n }\n\n function claim(address receiver) external nonReentrant returns (uint256) {\n return _claim(msg.sender, receiver);\n }\n\n /**\n * @notice compound delegation rewards\n */\n function compound() external nonReentrant whenNotPaused {\n _compound();\n }\n\n function updateRewards() external nonReentrant {\n _updateRewards(address(0));\n }\n\n function sendVestedFX(\n uint256 safeAmount\n ) external onlyVestedFX {\n address recipient = payable(msg.sender);\n (bool success, ) = recipient.call{value: safeAmount}(\"\");\n require(success, \"Failed to send FX\");\n }\n\n /**************************************** Internal and Private Functions ****************************************/\n /**\n * @dev Helper function to delegate FX amount to validators.\n * @param amount The amount: FX delegate to validators.\n */\n function _stake(uint256 amount) internal {\n VaultInfo memory vault = vaultInfo;\n uint256 totalAllocPoint = vault.totalAllocPoint;\n uint256 index = vault.stakeId;\n\n uint256 valLength = getValLength();\n uint256 _totalAssets = totalAssets();\n uint256 numValidators = _calculateNumberofValidators(amount);\n uint256 amountPerValidator = amount / numValidators;\n uint256 remainingAmount = amount;\n uint256 delegateAmount;\n\n while (remainingAmount != 0) {\n ValInfo memory val = valInfo[index];\n uint256 allocPoint = val.allocPoint;\n index = (index + 1) % valLength;\n\n if (allocPoint == 0) {\n continue;\n }\n \n if (_totalAssets >= CAP_STAKE_FX_TARGET) {\n delegateAmount = remainingAmount;\n } else {\n (, uint256 delegationAmount) = _delegation(val.validator, address(this));\n uint256 maxValSize = allocPoint * CAP_STAKE_FX_TARGET / totalAllocPoint;\n\n if (delegationAmount >= maxValSize) {\n continue;\n }\n\n if (remainingAmount <= amountPerValidator) {\n delegateAmount = remainingAmount;\n } else {\n delegateAmount = amountPerValidator;\n }\n }\n\n bool result = _delegateV2(val.validator, delegateAmount);\n require(result == true, \"delegate fail\");\n _totalAssets += delegateAmount;\n remainingAmount -= delegateAmount;\n }\n\n vaultInfo.stakeId = index;\n }\n\n /**\n * @dev Helper function to undelegate FX amount from validators.\n * @param amount The amount: FX to unstake from the vault.\n */\n function _unstake(uint256 amount) internal {\n VaultInfo memory vault = vaultInfo;\n uint256 index = vault.unstakeId;\n uint256 valLength = getValLength();\n\n uint256 remainingAmount = amount;\n uint256 totalReward; \n uint256 returnUndelegatedAmount;\n uint256 returnReward;\n \n // If contract byte size exceed limit, divide to half part can be removed\n if (amount >= UNSTAKE_FX_TARGET) {\n uint256 halfOfUndelegateAmount = amount / 2; \n (returnUndelegatedAmount) = _toUndelegate(index, halfOfUndelegateAmount);\n \n remainingAmount -= returnUndelegatedAmount;\n index = (index + 1) % valLength;\n totalReward += returnReward;\n }\n\n while (remainingAmount != 0) {\n (returnUndelegatedAmount) = _toUndelegate(index, remainingAmount);\n \n remainingAmount -= returnUndelegatedAmount;\n index = (index + 1) % valLength;\n totalReward += returnReward;\n }\n\n IVestedFX(vestedFX).lockWithEndTime(\n msg.sender, \n amount,\n block.timestamp + 21 days\n );\n\n vaultInfo.unstakeId = index;\n pendingFxReward += totalReward;\n }\n\n /**\n * @dev Helper function to undelegate FX amount from validators.\n * @param index Validator ID in validator list.\n * @param remainingAmount Amount to undelegate from validators.\n */\n function _toUndelegate(uint256 index, uint256 remainingAmount) internal returns(uint256) {\n (, uint256 delegationAmount) = _delegation(valInfo[index].validator, address(this));\n\n uint256 amountToUndelegate;\n\n if (delegationAmount > 0) {\n if (delegationAmount >= remainingAmount) {\n amountToUndelegate = remainingAmount;\n } else {\n amountToUndelegate = delegationAmount;\n }\n\n _undelegateV2(valInfo[index].validator, amountToUndelegate);\n }\n\n return amountToUndelegate;\n }\n\n /**\n * @dev Helper function to compound FX amount from validators.\n */\n function _compound() internal {\n _withdrawReward();\n uint256 delegateReward = pendingFxReward;\n pendingFxReward = 0;\n\n uint256 feeProtocol = (delegateReward * feeOnReward) / BIPS_DIVISOR;\n uint256 feeCompounder = (delegateReward * feeOnCompounder) / BIPS_DIVISOR;\n\n delegateReward = delegateReward - feeProtocol - feeCompounder;\n _stake(delegateReward);\n\n address treasury = payable(feeTreasury);\n address user = payable(msg.sender);\n (bool successTreasury, ) = treasury.call{value: feeProtocol}(\"\");\n (bool successUser, ) = user.call{value: feeCompounder}(\"\");\n require(successTreasury && successUser, \"Failed to send FX\");\n\n emit Compound(msg.sender, delegateReward);\n }\n\n /**\n * @dev Helper function to withdraw delegation fx rewards from all validators.\n */\n function _withdrawReward() internal {\n uint256 reward = 0;\n uint256 valLength = getValLength();\n\n for (uint256 i; i < valLength; i++) {\n string memory validator = valInfo[i].validator;\n uint256 delegationReward = _delegationRewards(validator, address(this));\n if(delegationReward > 0) {\n uint256 returnReward = _withdraw(validator);\n reward += returnReward;\n }\n }\n\n pendingFxReward += reward;\n }\n\n /**\n * @dev Helper function to help to calculate number of validator to delegate based on Log10 input amount.\n * @param delegateAmount Fx Amount to stake.\n * @return Number of validators to delegate.\n */\n function _calculateNumberofValidators(\n uint256 delegateAmount\n ) internal view returns (uint256) {\n uint256 numValidators;\n uint256 delegateAmountInEther = delegateAmount / 10**18;\n\n uint256 valLength = getValLength();\n while (delegateAmountInEther >= 10) {\n delegateAmountInEther /= 10;\n numValidators++;\n }\n\n return (numValidators == 0) ? 1 : (numValidators > valLength\n ? valLength\n : numValidators);\n }\n\n /**\n * @dev Helper function to help to query total FX delegation.\n */\n function _getUnderlyingFX() internal view returns (uint256) {\n uint256 totalAmount;\n uint256 valLength = getValLength();\n for (uint256 i; i < valLength; i++) {\n string memory validator = valInfo[i].validator;\n (, uint256 delegationAmount) = _delegation(validator, address(this));\n totalAmount += delegationAmount;\n }\n return totalAmount;\n }\n\n function _claim(address account, address receiver) private returns (uint256) {\n _updateRewards(account);\n UserInfo storage user = userInfo[account];\n uint256 tokenAmount = user.claimableReward;\n user.claimableReward = 0;\n\n if (tokenAmount > 0) {\n IERC20Upgradeable(rewardToken()).safeTransfer(receiver, tokenAmount);\n emit Claim(account, tokenAmount);\n }\n\n return tokenAmount;\n }\n\n function _updateRewards(address account) private {\n uint256 blockReward = IRewardDistributor(distributor).distribute();\n\n uint256 supply = totalSupply();\n uint256 _cumulativeRewardPerToken = vaultInfo.cumulativeRewardPerToken;\n if (supply > 0 && blockReward > 0) {\n _cumulativeRewardPerToken = _cumulativeRewardPerToken + (blockReward * (PRECISION) / (supply));\n vaultInfo.cumulativeRewardPerToken = _cumulativeRewardPerToken;\n }\n\n // cumulativeRewardPerToken can only increase\n // so if cumulativeRewardPerToken is zero, it means there are no rewards yet\n if (_cumulativeRewardPerToken == 0) {\n return;\n }\n\n if (account != address(0)) {\n UserInfo storage user = userInfo[account];\n uint256 stakedAmount = balanceOf(account);\n uint256 accountReward = stakedAmount * (_cumulativeRewardPerToken - (user.previousCumulatedRewardPerToken)) / (PRECISION);\n uint256 _claimableReward = user.claimableReward + (accountReward);\n\n user.claimableReward = _claimableReward;\n user.previousCumulatedRewardPerToken = _cumulativeRewardPerToken;\n }\n }\n\n function _beforeTokenTransfer(address from, address to, uint256 amount)\n internal\n whenNotPaused\n override\n {\n _updateRewards(from);\n _updateRewards(to);\n\n super._beforeTokenTransfer(from, to, amount);\n }\n\n function _authorizeUpgrade(\n address\n ) internal override onlyRole(OWNER_ROLE) {} \n\n\n /**************************************** Public/External View Functions ****************************************/\n\n /**\n * @notice Return total asset(FX) deposited\n * @return Amount of asset(FX) deposited\n */\n function totalAssets() public view override returns (uint256) {\n uint256 underlying = _getUnderlyingFX();\n return underlying;\n }\n\n function getValLength() public view returns (uint256) {\n return vaultInfo.length;\n }\n\n /**\n * @notice Return validator address and allocPoint\n */\n function getValInfo(uint256 index) public view returns (uint256, string memory) {\n return (valInfo[index].allocPoint, valInfo[index].validator);\n }\n\n /**\n * @notice Return total delegation reward\n */\n function getTotalDelegationRewards() public view returns (uint256) {\n uint256 totalAmount;\n uint256 valLength = getValLength();\n for (uint256 i; i < valLength; i++) {\n string memory validator = valInfo[i].validator;\n uint256 delegationReward = _delegationRewards(validator, address(this));\n totalAmount += delegationReward;\n }\n return totalAmount + pendingFxReward;\n }\n\n /**\n * @notice Return vault config(remove STAKE_FX_TARGET)\n */\n function getVaultConfigs() public view returns (uint256, uint256, uint256) {\n return (MIN_COMPOUND_AMOUNT, CAP_STAKE_FX_TARGET, UNSTAKE_FX_TARGET);\n }\n\n function rewardToken() public view returns (address) {\n return IRewardDistributor(distributor).rewardToken();\n }\n\n function claimable(address account) public view returns (uint256) {\n UserInfo memory user = userInfo[account];\n uint256 stakedAmount = balanceOf(account);\n if (stakedAmount == 0) {\n return user.claimableReward;\n }\n uint256 supply = totalSupply();\n uint256 pendingRewards = IRewardDistributor(distributor).pendingRewards() * (PRECISION);\n uint256 nextCumulativeRewardPerToken = vaultInfo.cumulativeRewardPerToken + (pendingRewards / (supply));\n return user.claimableReward + (\n stakedAmount * (nextCumulativeRewardPerToken - (user.previousCumulatedRewardPerToken)) / (PRECISION));\n }\n\n /**************************************** Only Governor Functions ****************************************/\n\n function redelegateValidator(\n uint256 srcId,\n uint256 dstId,\n uint256 redelegateAmount\n ) external onlyRole(GOVERNOR_ROLE) {\n require(srcId < vaultInfo.length && dstId < vaultInfo.length, \"Invalid ID\");\n ValInfo memory srcVal = valInfo[srcId];\n ValInfo memory dstVal = valInfo[dstId];\n (, uint256 delegationAmount) = _delegation(srcVal.validator, address(this));\n require(redelegateAmount <= delegationAmount, \"!Amount\");\n\n _compound();\n _redelegateV2(srcVal.validator, dstVal.validator, redelegateAmount);\n\n emit ValidatorRedelegated(srcVal.validator, dstVal.validator, redelegateAmount, redelegateAmount);\n }\n\n function addValidator(\n string memory _validator,\n uint256 _allocPoint\n ) external onlyRole(GOVERNOR_ROLE) {\n require(addedValidator[_validator] == false, \"addedVal\");\n valInfo[vaultInfo.length].validator = _validator;\n valInfo[vaultInfo.length].allocPoint = _allocPoint;\n\n vaultInfo.length++;\n vaultInfo.totalAllocPoint += _allocPoint;\n\n addedValidator[_validator]=true;\n\n emit ValidatorAdded(_validator, _allocPoint);\n }\n\n /**\n * @notice remove validators which has 0 allocPoint and 0 delegation in the list \n */\n function removeValidator() external onlyRole(GOVERNOR_ROLE) {\n uint256 valLength = getValLength();\n\n for (uint256 i = 0; i < valLength;) {\n if (valInfo[i].allocPoint == 0) {\n string memory val = valInfo[i].validator;\n (uint256 sharesAmount, ) = _delegation(val, address(this));\n\n if (sharesAmount == 0) {\n addedValidator[val] = false;\n uint256 lastIndex = valLength - 1;\n valInfo[i] = valInfo[lastIndex];\n delete valInfo[lastIndex];\n\n emit ValidatorRemoved(val);\n valLength--;\n // Skip if i == 0 to prevent underflow\n if (i == 0) {\n continue;\n } else {\n --i;\n }\n }\n }\n unchecked {\n ++i;\n }\n }\n // Reset stakeID, unstakeID, validator length\n vaultInfo.stakeId = 0;\n vaultInfo.unstakeId = 0;\n vaultInfo.length = valLength;\n }\n\n function updateValidator(\n uint256 id,\n uint256 newAllocPoint\n ) external onlyRole(GOVERNOR_ROLE) {\n require(id < vaultInfo.length, \"Invalid ID\");\n uint256 oldAllocPoint = valInfo[id].allocPoint;\n\n vaultInfo.totalAllocPoint = vaultInfo.totalAllocPoint + newAllocPoint - oldAllocPoint;\n valInfo[id].allocPoint = newAllocPoint;\n\n emit ValidatorUpdated(valInfo[id].validator, newAllocPoint);\n }\n\n /**\n * @notice Update vault config(remove STAKE_FX_TARGET)\n */\n function updateConfigs(uint256 newMinCompound, uint256 newCapStakeFxTarget, uint256 newUnstakeFxTarget) external onlyRole(GOVERNOR_ROLE) {\n MIN_COMPOUND_AMOUNT = newMinCompound;\n CAP_STAKE_FX_TARGET = newCapStakeFxTarget;\n UNSTAKE_FX_TARGET = newUnstakeFxTarget;\n }\n\n /**\n * @notice Update compounding fee percentage for protocol and compounder and user withdrawal percentage\n * require(newFeeOnReward + newFeeOnCompounder) <= BIPS_DIVISOR && newFeeOnWithdrawal <= BIPS_DIVISOR)\n */\n function updateFees(uint256 newFeeOnReward, uint256 newFeeOnCompounder, uint256 newFeeOnWithdrawal) external onlyRole(GOVERNOR_ROLE) {\n feeOnReward = newFeeOnReward;\n feeOnCompounder = newFeeOnCompounder;\n feeOnWithdrawal = newFeeOnWithdrawal;\n }\n\n /**************************************** Only Owner Functions ****************************************/\n\n function updateVestedFX(address newAddress) external onlyRole(OWNER_ROLE) {\n vestedFX = newAddress;\n emit VestedFXChanged(newAddress);\n }\n\n function updateFeeTreasury(address newAddress) external onlyRole(OWNER_ROLE) {\n feeTreasury = newAddress;\n emit FeeTreasuryChanged(newAddress);\n }\n \n function updateDistributor(address newAddress) external onlyRole(OWNER_ROLE) {\n distributor = newAddress;\n emit DistributorChanged(newAddress);\n }\n\n function recoverToken(\n address token,\n uint256 amount,\n address _recipient\n ) external onlyRole(OWNER_ROLE) {\n require(_recipient != address(0), \"Send to zero address\");\n if(token != address(0)) {\n IERC20Upgradeable(token).safeTransfer(_recipient, amount);\n } else {\n address recipient = payable(_recipient);\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Failed to send FX\");\n }\n }\n\n /**************************************************************\n * @dev Initialize the states\n *************************************************************/\n\n function initialize(\n address _asset,\n address _owner,\n address _governor\n ) public initializer {\n __BaseVaultInit(\n _asset,\n \"Staked FX Token\",\n \"StFX\",\n _owner,\n _governor\n );\n // __Governable_init(_owner, _governor); redundant code\n __UUPSUpgradeable_init();\n }\n}" + }, + "contracts/vaults/BaseVault.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.10;\n\nimport {PausableUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport {ERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport {IERC20MetadataUpgradeable, IERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport {ERC4626Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol\";\nimport {MathUpgradeable} from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\nimport {Governable} from \"../common/Governable.sol\";\n\nabstract contract BaseVault is Governable, PausableUpgradeable, ERC4626Upgradeable {\n using MathUpgradeable for uint256;\n\n function __BaseVaultInit(address _asset, string memory _name, string memory _symbol, address _owner, address _governor) internal{\n __ERC4626_init(IERC20MetadataUpgradeable(_asset));\n __ERC20_init(_name, _symbol);\n __Pausable_init();\n __AccessControl_init();\n\n __Governable_init(_owner, _governor);\n }\n\n // ============================= Revert functions ================================ //\n /**\n * @dev See {openzeppelin-IERC4626-deposit}.\n */\n function deposit(uint256 , address )\n public\n override\n returns (uint256)\n {\n revert(\"disabled\");\n }\n\n /**\n * @dev See {openzeppelin-IERC4626-mint}.\n */\n function mint(uint256 , address )\n public\n override\n returns (uint256)\n {\n revert(\"disabled\");\n }\n\n /**\n * @dev See {openzeppelin-IERC4626-withdraw}.\n */\n function withdraw(uint256 , address , address )\n public\n override\n returns (uint256)\n {\n revert(\"disabled\");\n }\n\n /**\n * @dev See {openzeppelin-IERC4626-redeem}.\n */\n function redeem(uint256 , address , address )\n public\n override\n returns (uint256)\n {\n revert(\"disabled\");\n }\n\n\n // ============================= Internal functions ================================ //\n /**\n * @dev Internal conversion function (from assets to shares) with support for rounding direction.\n *\n * Will revert if assets > 0, totalSupply > 0 and totalAssets = 0. That corresponds to a case where any asset\n * would represent an infinite amount of shares.\n */\n function _convertToShares(uint256 assets, MathUpgradeable.Rounding rounding) internal view override returns (uint256 shares) {\n uint256 supply = totalSupply();\n return\n (assets == 0 || supply == 0)\n ? _initialConvertToShares(assets, rounding)\n : assets.mulDiv(supply, totalAssets(), rounding);\n }\n\n /**\n * @dev Internal conversion function (from assets to shares) to apply when the vault is empty.\n *\n * NOTE: Make sure to keep this function consistent with {_initialConvertToAssets} when overriding it.\n */\n function _initialConvertToShares(\n uint256 assets,\n MathUpgradeable.Rounding /*rounding*/\n ) internal view virtual returns (uint256 shares) {\n return assets;\n }\n\n /**\n * @dev Internal conversion function (from shares to assets) with support for rounding direction.\n */\n function _convertToAssets(uint256 shares, MathUpgradeable.Rounding rounding) internal view override returns (uint256 assets) {\n uint256 supply = totalSupply();\n return\n (supply == 0) ? _initialConvertToAssets(shares, rounding) : shares.mulDiv(totalAssets(), supply, rounding);\n }\n\n /**\n * @dev Internal conversion function (from shares to assets) to apply when the vault is empty.\n *\n * NOTE: Make sure to keep this function consistent with {_initialConvertToShares} when overriding it.\n */\n function _initialConvertToAssets(\n uint256 shares,\n MathUpgradeable.Rounding /*rounding*/\n ) internal view virtual returns (uint256 assets) {\n return shares;\n }\n\n // ============================= Governable functions ================================ //\n\n function pause() public onlyRole(OWNER_ROLE) {\n _pause();\n }\n\n function unpause() public onlyRole(OWNER_ROLE) {\n _unpause();\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}" + }, "contracts/VestedFX.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\nimport {IStakeFXVault} from \"./interfaces/IStakeFXVault.sol\";\n\ncontract VestedFX is Initializable, UUPSUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable {\n \n using SafeERC20Upgradeable for IERC20Upgradeable;\n address private stakeFXVault;\n address private fxFeeTreasury;\n\n struct VestingSchedule {\n uint64 startTime;\n uint64 endTime;\n uint256 quantity;\n uint256 vestedQuantity;\n }\n\n /// @dev vesting schedule of an account\n mapping(address => VestingSchedule[]) private accountVestingSchedules;\n\n /// @dev An account's total escrowed balance per token to save recomputing this for fee extraction purposes\n mapping(address => uint256) public accountEscrowedBalance;\n\n /// @dev An account's total vested swap per token\n mapping(address => uint256) public accountVestedBalance;\n\n /* ========== EVENTS ========== */\n event VestingEntryCreated(address indexed beneficiary, uint256 startTime, uint256 endTime, uint256 quantity);\n event Vested(address indexed beneficiary, uint256 vestedQuantity, uint256 index);\n\n receive() external payable {}\n\n /* ========== MODIFIERS ========== */\n modifier onlyStakeFX() {\n require(msg.sender == (stakeFXVault), \"Only stakeFX can call\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /****************************************** Core Functions ******************************************/\n /**\n * @dev Allow a user to vest all ended schedules\n */\n function vestCompletedSchedules() public nonReentrant returns (uint256) {\n uint256 totalVesting = 0;\n totalVesting = _vestCompletedSchedules();\n\n return totalVesting;\n }\n\n /**************************************** View Functions ****************************************/\n /**\n * @notice The number of vesting dates in an account's schedule.\n */\n function numVestingSchedules(address account) external view returns (uint256) {\n return accountVestingSchedules[account].length;\n }\n\n /**\n * @dev manually get vesting schedule at index\n */\n function getVestingScheduleAtIndex(address account, uint256 index) external view returns (VestingSchedule memory) {\n return accountVestingSchedules[account][index];\n }\n\n /**\n * @dev Get all schedules for an account.\n */\n function getVestingSchedules(address account) external view returns (VestingSchedule[] memory) {\n return accountVestingSchedules[account];\n }\n\n function getstakeFXVault() external view returns (address) {\n return address(stakeFXVault);\n }\n\n function getFxFeeTreasury() external view returns (address) {\n return address(fxFeeTreasury);\n }\n\n /* ==================== INTERNAL FUNCTIONS ==================== */\n /**\n * @dev Allow a user to vest all ended schedules\n */\n function _vestCompletedSchedules() internal returns (uint256) {\n VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender];\n uint256 schedulesLength = schedules.length;\n\n uint256 totalVesting = 0;\n for (uint256 i = 0; i < schedulesLength; i++) {\n VestingSchedule memory schedule = schedules[i];\n if (_getBlockTime() < schedule.endTime) {\n continue;\n }\n\n uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity);\n if (vestQuantity == 0) {\n continue;\n }\n schedules[i].vestedQuantity = schedule.quantity;\n totalVesting = totalVesting + (vestQuantity);\n\n emit Vested(msg.sender, vestQuantity, i);\n }\n _completeVesting(totalVesting);\n _clearClaimedSchedule();\n \n return totalVesting;\n }\n\n function _completeVesting(uint256 totalVesting) internal {\n require(totalVesting != 0, '0 vesting amount');\n\n accountEscrowedBalance[msg.sender] = accountEscrowedBalance[msg.sender] - (totalVesting);\n accountVestedBalance[msg.sender] = accountVestedBalance[msg.sender] + (totalVesting);\n\n uint256 liquidity = (stakeFXVault).balance;\n\n if(liquidity < totalVesting) {\n uint256 feesTreasuryLiquidity = address(fxFeeTreasury).balance;\n require((liquidity + feesTreasuryLiquidity) >= totalVesting, \"Insuffient liq\");\n IStakeFXVault(fxFeeTreasury).sendVestedFX(totalVesting - liquidity);\n IStakeFXVault(stakeFXVault).sendVestedFX(liquidity);\n } else {\n IStakeFXVault(stakeFXVault).sendVestedFX(totalVesting);\n }\n address recipient = payable(msg.sender);\n (bool success, ) = recipient.call{value: totalVesting}(\"\");\n require(success, \"Failed to send FX\");\n }\n\n /**\n * @dev Delete User claimed schedule\n */\n function _clearClaimedSchedule() internal {\n VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender];\n uint256 schedulesLength = schedules.length;\n uint256 index;\n for (index = 0; index < schedulesLength; index++) {\n VestingSchedule memory schedule = schedules[index];\n\n uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity);\n if (vestQuantity == 0) {\n continue;\n } else {\n break;\n }\n }\n \n if (index != 0) { \n for(uint256 i = 0; i < schedules.length-index; i++) {\n schedules[i] = schedules[i+index]; \n }\n for(uint256 i = 0; i < index; i++) {\n schedules.pop();\n }\n }\n }\n\n /**\n * @dev wrap block.timestamp so we can easily mock it\n */\n function _getBlockTime() internal virtual view returns (uint32) {\n return uint32(block.timestamp);\n }\n\n /**************************************** Only Authorised Functions ****************************************/\n\n function lockWithEndTime(address account, uint256 quantity, uint256 endTime) external onlyStakeFX {\n require(quantity > 0, '0 quantity');\n\n VestingSchedule[] storage schedules = accountVestingSchedules[account];\n\n // append new schedule\n schedules.push(VestingSchedule({\n startTime: uint64(block.timestamp),\n endTime: uint64(endTime),\n quantity: quantity,\n vestedQuantity: 0\n }));\n\n // record total vesting balance of user\n accountEscrowedBalance[account] = accountEscrowedBalance[account] + (quantity);\n\n emit VestingEntryCreated(account, block.timestamp, endTime, quantity);\n }\n\n function recoverToken(address token, uint256 amount, address recipient) external onlyOwner {\n require(recipient != address(0), \"Send to zero address\");\n IERC20Upgradeable(token).safeTransfer(recipient, amount);\n }\n\n function updateStakeFXVault(address _stakeFXVault) external onlyOwner {\n stakeFXVault = _stakeFXVault;\n }\n\n function updateFxFeeTreasury(address _fxFeeTreasury) external onlyOwner {\n fxFeeTreasury = _fxFeeTreasury;\n }\n\n function _authorizeUpgrade(address) internal override onlyOwner {}\n\n /**************************************************************\n * @dev Initialize the states\n *************************************************************/\n\n function initialize(address _stakeFXVault, address _fxFeeTreasury) public initializer {\n stakeFXVault = _stakeFXVault;\n fxFeeTreasury = _fxFeeTreasury;\n\n __Ownable_init();\n __UUPSUpgradeable_init();\n }\n}" - }, - "contracts/VestedFXOld.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.18;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\nimport {IVestedFX} from \"./interfaces/IVestedFX.sol\"; // Only for testnet to migrate data from old contract,it will be removed in mainnet\nimport {IStakeFXVault} from \"./interfaces/IStakeFXVault.sol\";\n\ncontract VestedFXOld is Initializable, UUPSUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable {\n \n using SafeERC20Upgradeable for IERC20Upgradeable;\n address private stakeFXVault;\n address private fxFeeTreasury;\n\n struct VestingSchedule {\n uint64 startTime;\n uint64 endTime;\n uint256 quantity;\n uint256 vestedQuantity;\n }\n\n /// @dev vesting schedule of an account\n mapping(address => VestingSchedule[]) private accountVestingSchedules;\n\n /// @dev An account's total escrowed balance per token to save recomputing this for fee extraction purposes\n mapping(address => uint256) public accountEscrowedBalance;\n\n /// @dev An account's total vested swap per token\n mapping(address => uint256) public accountVestedBalance;\n\n /* ========== EVENTS ========== */\n event VestingEntryCreated(address indexed beneficiary, uint256 startTime, uint256 endTime, uint256 quantity);\n event Vested(address indexed beneficiary, uint256 vestedQuantity, uint256 index);\n\n receive() external payable {}\n\n /* ========== MODIFIERS ========== */\n modifier onlyStakeFX() {\n require(msg.sender == (stakeFXVault), \"Only stakeFX can call\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /****************************************** Core Functions ******************************************/\n /**\n * @dev Allow a user to vest all ended schedules\n */\n function vestCompletedSchedules() public nonReentrant returns (uint256) {\n uint256 totalVesting = 0;\n totalVesting = _vestCompletedSchedules();\n\n return totalVesting;\n }\n\n /**************************************** View Functions ****************************************/\n /**\n * @notice The number of vesting dates in an account's schedule.\n */\n function numVestingSchedules(address account) external view returns (uint256) {\n return accountVestingSchedules[account].length;\n }\n\n /**\n * @dev manually get vesting schedule at index\n */\n function getVestingScheduleAtIndex(address account, uint256 index) external view returns (VestingSchedule memory) {\n return accountVestingSchedules[account][index];\n }\n\n /**\n * @dev Get all schedules for an account.\n */\n function getVestingSchedules(address account) external view returns (VestingSchedule[] memory) {\n return accountVestingSchedules[account];\n }\n\n function getstakeFXVault() external view returns (address) {\n return address(stakeFXVault);\n }\n\n function getFxFeeTreasury() external view returns (address) {\n return address(fxFeeTreasury);\n }\n\n /* ==================== INTERNAL FUNCTIONS ==================== */\n /**\n * @dev Allow a user to vest all ended schedules\n */\n function _vestCompletedSchedules() internal returns (uint256) {\n VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender];\n uint256 schedulesLength = schedules.length;\n\n uint256 totalVesting = 0;\n for (uint256 i = 0; i < schedulesLength; i++) {\n VestingSchedule memory schedule = schedules[i];\n if (_getBlockTime() < schedule.endTime) {\n continue;\n }\n\n uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity);\n if (vestQuantity == 0) {\n continue;\n }\n schedules[i].vestedQuantity = schedule.quantity;\n totalVesting = totalVesting + (vestQuantity);\n\n emit Vested(msg.sender, vestQuantity, i);\n }\n _completeVesting(totalVesting);\n _clearClaimedSchedule();\n \n return totalVesting;\n }\n\n function _completeVesting(uint256 totalVesting) internal {\n require(totalVesting != 0, '0 vesting amount');\n\n accountEscrowedBalance[msg.sender] = accountEscrowedBalance[msg.sender] - (totalVesting);\n accountVestedBalance[msg.sender] = accountVestedBalance[msg.sender] + (totalVesting);\n\n uint256 liquidity = (stakeFXVault).balance;\n\n if(liquidity < totalVesting) {\n uint256 feesTreasuryLiquidity = address(fxFeeTreasury).balance;\n require((liquidity + feesTreasuryLiquidity) >= totalVesting, \"Insuffient liq\");\n IStakeFXVault(fxFeeTreasury).sendVestedFX(totalVesting - liquidity);\n IStakeFXVault(stakeFXVault).sendVestedFX(liquidity);\n } else {\n IStakeFXVault(stakeFXVault).sendVestedFX(totalVesting);\n }\n address recipient = payable(msg.sender);\n (bool success, ) = recipient.call{value: totalVesting}(\"\");\n require(success, \"Failed to send FX\");\n }\n\n /**\n * @dev Delete User claimed schedule\n */\n // function _clearClaimedSchedule() internal {\n // VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender];\n // uint256 schedulesLength = schedules.length;\n\n // for (uint256 i = 0; i < schedulesLength; i++) {\n // VestingSchedule memory schedule = schedules[i];\n\n // uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity);\n // if (vestQuantity == 0) {\n // continue;\n // } else {\n // uint256 index = i;\n // for(uint256 i = 0; i < schedules.length-index; i++) {\n // schedules[i] = schedules[i+index]; \n // }\n // for(uint256 i = 0; i < index; i++) {\n // schedules.pop();\n // }\n // break; \n // }\n // }\n // }\n function _clearClaimedSchedule() internal {\n VestingSchedule[] storage schedules = accountVestingSchedules[msg.sender];\n uint256 schedulesLength = schedules.length;\n uint256 index;\n for (index = 0; index < schedulesLength; index++) {\n VestingSchedule memory schedule = schedules[index];\n\n uint256 vestQuantity = (schedule.quantity) - (schedule.vestedQuantity);\n if (vestQuantity == 0) {\n continue;\n } else {\n break;\n }\n }\n \n if (index !=0) { \n for(uint256 i = 0; i < schedules.length-index; i++) {\n schedules[i] = schedules[i+index]; \n }\n for(uint256 i = 0; i < index; i++) {\n schedules.pop();\n }\n }\n }\n\n /**\n * @dev wrap block.timestamp so we can easily mock it\n */\n function _getBlockTime() internal virtual view returns (uint32) {\n return uint32(block.timestamp);\n }\n\n /**************************************** Only Authorised Functions ****************************************/\n\n function lockWithEndTime(address account, uint256 quantity, uint256 endTime) external onlyStakeFX {\n require(quantity > 0, '0 quantity');\n\n VestingSchedule[] storage schedules = accountVestingSchedules[account];\n\n // append new schedule\n schedules.push(VestingSchedule({\n startTime: uint64(block.timestamp),\n endTime: uint64(endTime),\n quantity: quantity,\n vestedQuantity: 0\n }));\n\n // record total vesting balance of user\n accountEscrowedBalance[account] = accountEscrowedBalance[account] + (quantity);\n\n emit VestingEntryCreated(account, block.timestamp, endTime, quantity);\n }\n\n /**\n * @dev Only for testnet to migrate data from old contract,it will be removed in mainnet\n */\n function migrateData(address account) external onlyOwner {\n require(account != address(0), '0 quantity');\n address oldVestedFX = 0xEe541f260C9fa4bFED73fF97C1dfB0483A684259;\n VestingSchedule[] storage schedules = accountVestingSchedules[account];\n IVestedFX.VestingSchedule[] memory oldSchedules;\n\n oldSchedules = IVestedFX(oldVestedFX).getVestingSchedules(account);\n uint256 oldAccountEscrowedBalance = IVestedFX(oldVestedFX).accountEscrowedBalance(account);\n uint256 oldAccountVestedBalance = IVestedFX(oldVestedFX).accountVestedBalance(account);\n\n // append new schedule\n for (uint256 i = 0; i < oldSchedules.length; i++) {\n schedules.push(\n VestingSchedule({\n startTime: uint64(oldSchedules[i].startTime),\n endTime: uint64(oldSchedules[i].endTime),\n quantity: oldSchedules[i].quantity,\n vestedQuantity: oldSchedules[i].vestedQuantity\n })\n );\n }\n\n // record total vesting balance of user\n accountEscrowedBalance[account] = oldAccountEscrowedBalance;\n accountVestedBalance[account] = oldAccountVestedBalance;\n }\n\n function recoverToken(address token, uint256 amount, address recipient) external onlyOwner nonReentrant{\n require(recipient != address(0), \"Send to zero address\");\n IERC20Upgradeable(token).safeTransfer(recipient, amount);\n }\n\n function updateStakeFXVault(address _stakeFXVault) external onlyOwner nonReentrant{\n stakeFXVault = _stakeFXVault;\n }\n\n function updateFxFeeTreasury(address _fxFeeTreasury) external onlyOwner {\n fxFeeTreasury = _fxFeeTreasury;\n }\n\n function _authorizeUpgrade(address) internal override onlyOwner {}\n\n /**************************************************************\n * @dev Initialize the states\n *************************************************************/\n\n function initialize(address _stakeFXVault, address _fxFeeTreasury) public initializer {\n stakeFXVault = _stakeFXVault;\n fxFeeTreasury = _fxFeeTreasury;\n\n __Ownable_init();\n __UUPSUpgradeable_init();\n }\n}" } }, "settings": {