├── .codecov.yml
├── .env_example
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .mocharc.json
├── .solcover.js
├── .solhint.json
├── .solhintignore
├── LICENSE
├── README.md
├── codechecks.yml
├── contracts
├── TetuBridgedProcessing.sol
├── TetuTokenMainnet.sol
├── infrastructure
│ ├── ControllerV2.sol
│ ├── ForwarderV3.sol
│ ├── ForwarderV4.sol
│ ├── InvestFundV2.sol
│ └── PlatformVoter.sol
├── interfaces
│ ├── IBVault.sol
│ ├── IBribe.sol
│ ├── IControllable.sol
│ ├── IController.sol
│ ├── IERC165.sol
│ ├── IERC20.sol
│ ├── IERC20Metadata.sol
│ ├── IERC20Permit.sol
│ ├── IERC4626.sol
│ ├── IERC721.sol
│ ├── IERC721Metadata.sol
│ ├── IERC721Receiver.sol
│ ├── IForwarder.sol
│ ├── IGauge.sol
│ ├── IMultiPool.sol
│ ├── IPlatformVoter.sol
│ ├── IPriceOracle.sol
│ ├── IProxyControlled.sol
│ ├── ISmartVault.sol
│ ├── ISplitter.sol
│ ├── IStrategyStrict.sol
│ ├── IStrategyV2.sol
│ ├── IStrategyV3.sol
│ ├── ITetuLiquidator.sol
│ ├── ITetuVaultV2.sol
│ ├── IVaultInsurance.sol
│ ├── IVeDistributor.sol
│ ├── IVeDistributorV2.sol
│ ├── IVeTetu.sol
│ ├── IVeVotable.sol
│ └── IVoter.sol
├── lib
│ ├── Base64.sol
│ ├── InterfaceIds.sol
│ ├── SlotsLib.sol
│ └── StringLib.sol
├── openzeppelin
│ ├── Address.sol
│ ├── Clones.sol
│ ├── Context.sol
│ ├── ContextUpgradeable.sol
│ ├── Counters.sol
│ ├── CountersUpgradeable.sol
│ ├── ECDSA.sol
│ ├── ECDSAUpgradeable.sol
│ ├── EIP712.sol
│ ├── EIP712Upgradeable.sol
│ ├── ERC165.sol
│ ├── ERC20.sol
│ ├── ERC20Permit.sol
│ ├── ERC20PermitUpgradeable.sol
│ ├── ERC20Upgradeable.sol
│ ├── EnumerableMap.sol
│ ├── EnumerableSet.sol
│ ├── Initializable.sol
│ ├── Math.sol
│ ├── Proxy.sol
│ ├── ReentrancyGuard.sol
│ ├── SafeERC20.sol
│ └── Strings.sol
├── proxy
│ ├── ControllableV3.sol
│ ├── ProxyControlled.sol
│ └── UpgradeableProxy.sol
├── reward
│ ├── MultiBribe.sol
│ ├── MultiGauge.sol
│ ├── MultiGaugeNoBoost.sol
│ └── StakelessMultiPoolBase.sol
├── strategy
│ ├── StrategyBaseV2.sol
│ ├── StrategyBaseV3.sol
│ ├── StrategyLib.sol
│ ├── StrategyLib2.sol
│ └── StrategyStrictBase.sol
├── test
│ ├── Base64Test.sol
│ ├── ControllableTest.sol
│ ├── ControllerMinimal.sol
│ ├── IControllerV1.sol
│ ├── IMockToken.sol
│ ├── MockBribe.sol
│ ├── MockForwarder.sol
│ ├── MockGauge.sol
│ ├── MockLiquidator.sol
│ ├── MockPawnshop.sol
│ ├── MockPool.sol
│ ├── MockSplitter.sol
│ ├── MockStakingToken.sol
│ ├── MockStrategy.sol
│ ├── MockStrategySimple.sol
│ ├── MockStrategyStrict.sol
│ ├── MockStrategyV3.sol
│ ├── MockToken.sol
│ ├── MockVault.sol
│ ├── MockVaultSimple.sol
│ ├── MockVeDist.sol
│ ├── MockVoter.sol
│ ├── Multicall.sol
│ ├── SlotsTest.sol
│ ├── StakelessMultiPoolMock.sol
│ ├── StrategyV2BaseEmpty.sol
│ ├── StrategyV3BaseEmpty.sol
│ ├── StringLibFacade.sol
│ ├── TetuERC165Test.sol
│ └── WrongNFTReceiver.sol
├── tools
│ ├── ArbitragePoolSolidly.sol
│ ├── ArbitrageVaultSolidly.sol
│ ├── ArbitrageVaultUni3._sol
│ ├── BribeDistribution.sol
│ ├── DepositHelperAbstract.sol
│ ├── DepositHelperBaseChain.sol
│ ├── DepositHelperPolygon.sol
│ ├── DepositHelperSimplified.sol
│ ├── ForwarderDistributeResolver.sol
│ ├── HardWorkResolver.sol
│ ├── ISolidlyPair.sol
│ ├── PerfFeeTreasury.sol
│ ├── RewardsRedirector.sol
│ ├── SplitterRebalanceResolver.sol
│ └── TetuERC165.sol
├── vault
│ ├── ERC4626.sol
│ ├── ERC4626Strict.sol
│ ├── ERC4626Upgradeable.sol
│ ├── StrategySplitterV2.sol
│ ├── TetuVaultV2.sol
│ ├── VaultFactory.sol
│ └── VaultInsurance.sol
└── ve
│ ├── TetuEmitter.sol
│ ├── TetuVoter.sol
│ ├── TetuVoterSimplified.sol
│ ├── VeDistributor.sol
│ ├── VeDistributorV2.sol
│ ├── VeTetu.sol
│ └── VeTetuLib.sol
├── hardhat.config.ts
├── log_settings.ts
├── package-lock.json
├── package.json
├── scripts
├── addresses
│ ├── addresses.ts
│ ├── base.ts
│ ├── goerli.ts
│ ├── polygon.ts
│ ├── sepolia.ts
│ └── zkevm.ts
├── deploy
│ ├── DeployAllProd.ts
│ ├── DeployAllProdSimplified.ts
│ ├── DeployAllTestnet.ts
│ ├── DeployBribeDistribution.ts
│ ├── DeployContract.ts
│ ├── DeployDepositHelperBaseChain.ts
│ ├── DeployDepositHelperPolygon.ts
│ ├── DeployForwarderResolver.ts
│ ├── DeployHardworkResolver.ts
│ ├── DeployInvestFund.ts
│ ├── DeployMockStrategy.ts
│ ├── DeployMockToken.ts
│ ├── DeployPerfFeeTreasury.ts
│ ├── DeployRewardsRedirector.ts
│ ├── DeploySplitterRebalanceResolver.ts
│ ├── DeployTetuBridgedProcessing.ts
│ ├── DeployVault.ts
│ └── DeployVaultFactory.ts
├── gov
│ ├── execute-upgrades.ts
│ ├── poke-gauge-voter.ts
│ ├── poke-platform-voter.ts
│ └── simulate-remove-all-platform-votes.ts
├── models
│ ├── CoreAddresses.ts
│ └── ToolsAddresses.ts
├── test
│ ├── CreateMockPair.ts
│ └── MakeNoizeOnTestnet.ts
└── utils
│ ├── DeployerUtils.ts
│ ├── Misc.ts
│ ├── RunHelper.ts
│ ├── UpdateBlock.ts
│ ├── VerifyUtils.ts
│ └── Web3Utils.ts
├── slither.config.json
├── slither.db.json
├── test
├── TestAsserts.ts
├── TetuBridgedProcessingTest.ts
├── TimeUtils.ts
├── TokenUtils.ts
├── infrastructure
│ ├── ControllerV2Test.ts
│ ├── ForwarderTest.ts
│ ├── InvestFundV2Test.ts
│ └── PlatformVoterTest.ts
├── lib
│ ├── Base64Test.ts
│ ├── SlotsTest.ts
│ └── StringLibTest.ts
├── proxy
│ ├── ControllableTest.ts
│ └── ProxyTest.ts
├── reward
│ ├── MultiBribeTest.ts
│ ├── MultiGaugeTest.ts
│ └── MultiPoolTest.ts
├── test-utils.ts
├── tools
│ ├── ArbitragePoolSolidlyTest.ts
│ ├── ArbitrageVaultSolidlyTest.ts
│ ├── BribeDistributorTest.ts
│ ├── DepositHelperTests.ts
│ ├── DepositHelperTestsBase.ts
│ ├── DepositHelperTestsPolygon.ts
│ ├── DepositHelperTestsSimplified.ts
│ ├── HardWorkResolverTest.ts
│ ├── PerfFeeTreasuryTest.ts
│ ├── RewardsRedirectorTest.ts
│ ├── SplitterRebalanceResolverTest.ts
│ └── TetuERC165Test.ts
├── vault
│ ├── BaseVaultTests.ts
│ ├── CheckWithdrawImpactTest.ts
│ ├── ERC4626StrictTests.ts
│ ├── SplitterForBaseStrategyV3Tests.ts
│ ├── SplitterTests.ts
│ ├── StrategyBaseV2Tests.ts
│ ├── StrategyBaseV3Tests.ts
│ ├── TetuVaultV2Tests.ts
│ ├── VaultFactoryPolygonTests.ts
│ └── VaultFactoryTests.ts
└── ve
│ ├── TetuEmitterTest.ts
│ ├── TetuVoterSimplifiedTest.ts
│ ├── TetuVoterTest.ts
│ ├── VeDistributorTest.ts
│ ├── VeDistributorV2Test.ts
│ ├── VeDistributorWithAlwaysMaxLockTest.ts
│ ├── VeTetuIntegrationTestPolygon.ts
│ └── VeTetuTest.ts
├── tetu_contracts.svg
├── tsconfig.json
├── tslint.json
└── veTETU.svg
/.codecov.yml:
--------------------------------------------------------------------------------
1 | comment:
2 | layout: "reach,diff,flags,files,footer"
3 | behavior: default
4 | require_changes: false
5 | github_checks:
6 | comment: true
7 | annotations: true
8 | coverage:
9 | status:
10 | patch:
11 | default:
12 | target: 100%
13 | ignore:
14 | - "contracts/test"
15 | - "contracts/integrations"
16 | - "contracts/openzeppelin"
17 | - "contracts/tools"
18 |
--------------------------------------------------------------------------------
/.env_example:
--------------------------------------------------------------------------------
1 | TETU_MATIC_RPC_URL=https://polygon-mainnet.g.alchemy.com/v2/key
2 | TETU_FTM_RPC_URL=rpc_url
3 |
4 | ___not_necessary_if_you_dont_want_to_deploy___
5 |
6 | TETU_PRIVATE_KEY=deployer_key
7 |
8 | TETU_NETWORK_SCAN_KEY=key
9 | TETU_NETWORK_SCAN_KEY_MATIC=
10 | TETU_NETWORK_SCAN_KEY_FTM=
11 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Unit tests + coverage
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - release-*
8 | pull_request: { }
9 | workflow_dispatch: { }
10 |
11 | jobs:
12 |
13 | coverage:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v2
17 | with:
18 | fetch-depth: 2
19 | - uses: actions/setup-node@v2
20 | with:
21 | node-version: 18.x
22 | - uses: actions/cache@v2
23 | id: cache
24 | with:
25 | path: '**/node_modules'
26 | key: npm-v2-${{ hashFiles('**/package-lock.json') }}
27 | restore-keys: npm-v2-
28 | - run: npm ci
29 | if: steps.cache.outputs.cache-hit != 'true'
30 | - run: npm run coverage
31 | env:
32 | NODE_OPTIONS: --max_old_space_size=4096
33 | - uses: codecov/codecov-action@v2
34 | with:
35 | token: ${{secrets.CODECOV_TOKEN}}
36 | fail_ci_if_error: true
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn.lock
3 |
4 | #Hardhat files
5 | cache
6 | artifacts
7 | deployments
8 | typechain
9 | coverage
10 | coverage.json
11 | dist
12 |
13 | .idea
14 | .hardhat
15 | secrets.ts
16 | .openzeppelin
17 | .tenderly
18 | arguments-*.js
19 | sh
20 | tmp
21 | settings.ts
22 | token_addresses.txt
23 | core_addresses.txt
24 | tool_addresses.txt
25 | .env
26 | docs
27 | abi
28 |
--------------------------------------------------------------------------------
/.mocharc.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": "ts-node/register/files",
3 | "timeout": 9999999999999
4 | }
5 |
--------------------------------------------------------------------------------
/.solcover.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | skipFiles: ['test', 'integrations', 'openzeppelin', 'tools']
3 | };
4 |
--------------------------------------------------------------------------------
/.solhint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "solhint:recommended",
3 | "plugins": [],
4 | "rules": {
5 | "compiler-version": [
6 | "error",
7 | "^0.8.4"
8 | ],
9 | "func-visibility": [
10 | "off",
11 | {
12 | "ignoreConstructors": true
13 | }
14 | ],
15 | "avoid-tx-origin": "off",
16 | "not-rely-on-time": "off",
17 | "no-empty-blocks": "off",
18 | "no-inline-assembly": "off",
19 | "avoid-low-level-calls": "off",
20 | "avoid-suicide": "error",
21 | "code-complexity": [
22 | "warn",
23 | 20
24 | ],
25 | "function-max-lines": [
26 | "warn",
27 | 150
28 | ],
29 | "max-line-length": [
30 | "error",
31 | 120
32 | ],
33 | "constructor-syntax": "warn",
34 | "avoid-sha3": "warn",
35 | "indent": "off",
36 | "bracket-align": "off",
37 | "expression-indent": "off",
38 | "mark-callable-contracts": "off",
39 | "comprehensive-interface": "warn"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/.solhintignore:
--------------------------------------------------------------------------------
1 | contracts/test
2 | contracts/integrations
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
2 | [](https://codecov.io/gh/tetu-io/tetu-contracts-v2)
3 |
4 | ## Links
5 |
6 | Web: https://tetu.io/
7 |
8 | Docs: https://docs.tetu.io/
9 |
10 | Discord: https://discord.gg/DSUKVEYuax
11 |
12 | Twitter: https://twitter.com/tetu_io
13 |
14 |
15 | TETU mainnet https://etherscan.io/address/0x0F72964Fa4b766521d84107991E837c30D0EF2b1#code
16 |
--------------------------------------------------------------------------------
/codechecks.yml:
--------------------------------------------------------------------------------
1 | checks:
2 | - name: eth-gas-reporter/codechecks
3 |
--------------------------------------------------------------------------------
/contracts/TetuBridgedProcessing.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./interfaces/IERC20.sol";
6 |
7 | /// @title Contract for handling TETU from mainnet bridged via Polygon native bridge.
8 | /// @author belbix
9 | contract TetuBridgedProcessing {
10 |
11 | //////////// EVENTS ///////////////
12 |
13 | event OfferAdmin(address newAdmin);
14 | event AcceptAdmin(address newAdmin);
15 | event PauseOn();
16 | event PauseOff();
17 | event BridgeTetu(address user, uint amount);
18 | event ClaimTetu(address user, uint amount);
19 |
20 | //////////// VARIABLES ///////////////
21 |
22 | IERC20 public immutable tetu;
23 | IERC20 public immutable tetuBridged;
24 | address public admin;
25 | address public pendingAdmin;
26 | bool public paused;
27 |
28 | constructor(address _tetu, address _tetuBridged, address _admin) {
29 | tetu = IERC20(_tetu);
30 | tetuBridged = IERC20(_tetuBridged);
31 | admin = _admin;
32 | }
33 |
34 | //////////// ADMIN ACTIONS ///////////////
35 |
36 | function offerAdmin(address adr) external {
37 | require(msg.sender == admin, "!admin");
38 | pendingAdmin = adr;
39 | emit OfferAdmin(adr);
40 | }
41 |
42 | function acceptAdmin() external {
43 | require(msg.sender == pendingAdmin, "!admin");
44 | admin = msg.sender;
45 | pendingAdmin = address(0);
46 | emit AcceptAdmin(msg.sender);
47 | }
48 |
49 | function pauseOn() external {
50 | require(msg.sender == admin, "!admin");
51 | paused = true;
52 | emit PauseOn();
53 | }
54 |
55 | function pauseOff() external {
56 | require(msg.sender == admin, "!admin");
57 | paused = false;
58 | emit PauseOff();
59 | }
60 |
61 | //////////// MAIN ACTIONS ///////////////
62 |
63 | function bridgeTetuToMainnet(uint amount) external {
64 | require(!paused, "paused");
65 | tetu.transferFrom(msg.sender, address(this), amount);
66 | tetuBridged.transfer(msg.sender, amount);
67 | emit BridgeTetu(msg.sender, amount);
68 | }
69 |
70 | function claimBridgedTetu(uint amount) external {
71 | require(!paused, "paused");
72 | tetuBridged.transferFrom(msg.sender, address(this), amount);
73 | tetu.transfer(msg.sender, amount);
74 | emit ClaimTetu(msg.sender, amount);
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/contracts/TetuTokenMainnet.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./openzeppelin/ERC20Permit.sol";
6 |
7 | contract TetuTokenMainnet is ERC20Permit {
8 |
9 | constructor() ERC20("Tetu Token", "TETU") ERC20Permit("Tetu Token") {
10 | // premint max possible supply for using them in a bridging process
11 | _mint(msg.sender, 1_000_000_000e18);
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/contracts/interfaces/IBribe.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IBribe {
6 |
7 | function epoch() external view returns (uint);
8 |
9 | function getReward(
10 | address vault,
11 | uint veId,
12 | address[] memory tokens
13 | ) external;
14 |
15 | function getAllRewards(
16 | address vault,
17 | uint veId
18 | ) external;
19 |
20 | function getAllRewardsForTokens(
21 | address[] memory vaults,
22 | uint veId
23 | ) external;
24 |
25 | function deposit(address vault, uint amount, uint tokenId) external;
26 |
27 | function withdraw(address vault, uint amount, uint tokenId) external;
28 |
29 | function notifyRewardAmount(address vault, address token, uint amount) external;
30 |
31 | function notifyForNextEpoch(address vault, address token, uint amount) external;
32 |
33 | function notifyDelayedRewards(address vault, address token, uint _epoch) external;
34 |
35 | function increaseEpoch() external;
36 |
37 | function rewardsQueue(address vault, address rt, uint epoch) external view returns (uint);
38 | }
39 |
--------------------------------------------------------------------------------
/contracts/interfaces/IControllable.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IControllable {
6 |
7 | function isController(address _contract) external view returns (bool);
8 |
9 | function isGovernance(address _contract) external view returns (bool);
10 |
11 | function created() external view returns (uint256);
12 |
13 | function createdBlock() external view returns (uint256);
14 |
15 | function controller() external view returns (address);
16 |
17 | function increaseRevision(address oldLogic) external;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/contracts/interfaces/IController.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IController {
6 |
7 | // --- DEPENDENCY ADDRESSES
8 | function governance() external view returns (address);
9 |
10 | function voter() external view returns (address);
11 |
12 | function liquidator() external view returns (address);
13 |
14 | function forwarder() external view returns (address);
15 |
16 | function investFund() external view returns (address);
17 |
18 | // deprecated
19 | // function veDistributor() external view returns (address);
20 |
21 | function platformVoter() external view returns (address);
22 |
23 | // --- VAULTS
24 |
25 | function vaults(uint id) external view returns (address);
26 |
27 | function vaultsList() external view returns (address[] memory);
28 |
29 | function vaultsListLength() external view returns (uint);
30 |
31 | function isValidVault(address _vault) external view returns (bool);
32 |
33 | // --- restrictions
34 |
35 | function isOperator(address _adr) external view returns (bool);
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC165.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | /**
6 | * @dev Interface of the ERC165 standard, as defined in the
7 | * https://eips.ethereum.org/EIPS/eip-165[EIP].
8 | *
9 | * Implementers can declare support of contract interfaces, which can then be
10 | * queried by others ({ERC165Checker}).
11 | *
12 | * For an implementation, see {ERC165}.
13 | */
14 | interface IERC165 {
15 | /**
16 | * @dev Returns true if this contract implements the interface defined by
17 | * `interfaceId`. See the corresponding
18 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
19 | * to learn more about how these ids are created.
20 | *
21 | * This function call must use less than 30 000 gas.
22 | */
23 | function supportsInterface(bytes4 interfaceId) external view returns (bool);
24 | }
25 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC20.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | /**
6 | * @dev Interface of the ERC20 standard as defined in the EIP.
7 | */
8 | interface IERC20 {
9 | /**
10 | * @dev Returns the amount of tokens in existence.
11 | */
12 | function totalSupply() external view returns (uint);
13 |
14 | /**
15 | * @dev Returns the amount of tokens owned by `account`.
16 | */
17 | function balanceOf(address account) external view returns (uint);
18 |
19 | /**
20 | * @dev Moves `amount` tokens from the caller's account to `recipient`.
21 | *
22 | * Returns a boolean value indicating whether the operation succeeded.
23 | *
24 | * Emits a {Transfer} event.
25 | */
26 | function transfer(address recipient, uint amount) external returns (bool);
27 |
28 | /**
29 | * @dev Returns the remaining number of tokens that `spender` will be
30 | * allowed to spend on behalf of `owner` through {transferFrom}. This is
31 | * zero by default.
32 | *
33 | * This value changes when {approve} or {transferFrom} are called.
34 | */
35 | function allowance(address owner, address spender) external view returns (uint);
36 |
37 | /**
38 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
39 | *
40 | * Returns a boolean value indicating whether the operation succeeded.
41 | *
42 | * IMPORTANT: Beware that changing an allowance with this method brings the risk
43 | * that someone may use both the old and the new allowance by unfortunate
44 | * transaction ordering. One possible solution to mitigate this race
45 | * condition is to first reduce the spender's allowance to 0 and set the
46 | * desired value afterwards:
47 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
48 | *
49 | * Emits an {Approval} event.
50 | */
51 | function approve(address spender, uint amount) external returns (bool);
52 |
53 | /**
54 | * @dev Moves `amount` tokens from `sender` to `recipient` using the
55 | * allowance mechanism. `amount` is then deducted from the caller's
56 | * allowance.
57 | *
58 | * Returns a boolean value indicating whether the operation succeeded.
59 | *
60 | * Emits a {Transfer} event.
61 | */
62 | function transferFrom(
63 | address sender,
64 | address recipient,
65 | uint amount
66 | ) external returns (bool);
67 |
68 | /**
69 | * @dev Emitted when `value` tokens are moved from one account (`from`) to
70 | * another (`to`).
71 | *
72 | * Note that `value` may be zero.
73 | */
74 | event Transfer(address indexed from, address indexed to, uint value);
75 |
76 | /**
77 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by
78 | * a call to {approve}. `value` is the new allowance.
79 | */
80 | event Approval(address indexed owner, address indexed spender, uint value);
81 | }
82 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC20Metadata.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | import "./IERC20.sol";
7 |
8 | /**
9 | * https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/release-v4.6/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol
10 | * @dev Interface for the optional metadata functions from the ERC20 standard.
11 | *
12 | * _Available since v4.1._
13 | */
14 | interface IERC20Metadata is IERC20 {
15 | /**
16 | * @dev Returns the name of the token.
17 | */
18 | function name() external view returns (string memory);
19 |
20 | /**
21 | * @dev Returns the symbol of the token.
22 | */
23 | function symbol() external view returns (string memory);
24 |
25 | /**
26 | * @dev Returns the decimals places of the token.
27 | */
28 | function decimals() external view returns (uint8);
29 | }
30 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC20Permit.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | /**
7 | * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
8 | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
9 | *
10 | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
11 | * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
12 | * need to send a transaction, and thus is not required to hold Ether at all.
13 | */
14 | interface IERC20Permit {
15 | /**
16 | * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
17 | * given ``owner``'s signed approval.
18 | *
19 | * IMPORTANT: The same issues {IERC20-approve} has related to transaction
20 | * ordering also apply here.
21 | *
22 | * Emits an {Approval} event.
23 | *
24 | * Requirements:
25 | *
26 | * - `spender` cannot be the zero address.
27 | * - `deadline` must be a timestamp in the future.
28 | * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
29 | * over the EIP712-formatted function arguments.
30 | * - the signature must use ``owner``'s current nonce (see {nonces}).
31 | *
32 | * For more information on the signature format, see the
33 | * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
34 | * section].
35 | */
36 | function permit(
37 | address owner,
38 | address spender,
39 | uint256 value,
40 | uint256 deadline,
41 | uint8 v,
42 | bytes32 r,
43 | bytes32 s
44 | ) external;
45 |
46 | /**
47 | * @dev Returns the current nonce for `owner`. This value must be
48 | * included whenever a signature is generated for {permit}.
49 | *
50 | * Every successful call to {permit} increases ``owner``'s nonce by one. This
51 | * prevents a signature from being used multiple times.
52 | */
53 | function nonces(address owner) external view returns (uint256);
54 |
55 | /**
56 | * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
57 | */
58 | // solhint-disable-next-line func-name-mixedcase
59 | function DOMAIN_SEPARATOR() external view returns (bytes32);
60 | }
61 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC721Metadata.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./IERC721.sol";
6 |
7 | /**
8 | * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
9 | * @dev See https://eips.ethereum.org/EIPS/eip-721
10 | */
11 | interface IERC721Metadata is IERC721 {
12 | /**
13 | * @dev Returns the token collection name.
14 | */
15 | function name() external view returns (string memory);
16 |
17 | /**
18 | * @dev Returns the token collection symbol.
19 | */
20 | function symbol() external view returns (string memory);
21 |
22 | /**
23 | * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
24 | */
25 | function tokenURI(uint tokenId) external view returns (string memory);
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC721Receiver.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | /**
6 | * @title ERC721 token receiver interface
7 | * @dev Interface for any contract that wants to support safeTransfers
8 | * from ERC721 asset contracts.
9 | */
10 | interface IERC721Receiver {
11 | /**
12 | * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
13 | * by `operator` from `from`, this function is called.
14 | *
15 | * It must return its Solidity selector to confirm the token transfer.
16 | * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
17 | *
18 | * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
19 | */
20 | function onERC721Received(
21 | address operator,
22 | address from,
23 | uint256 tokenId,
24 | bytes calldata data
25 | ) external returns (bytes4);
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/interfaces/IForwarder.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IForwarder {
6 |
7 | function tetu() external view returns (address);
8 | function tetuThreshold() external view returns (uint);
9 |
10 | function tokenPerDestinationLength(address destination) external view returns (uint);
11 |
12 | function tokenPerDestinationAt(address destination, uint i) external view returns (address);
13 |
14 | function amountPerDestination(address token, address destination) external view returns (uint amount);
15 |
16 | function registerIncome(
17 | address[] memory tokens,
18 | uint[] memory amounts,
19 | address vault,
20 | bool isDistribute
21 | ) external;
22 |
23 | function distributeAll(address destination) external;
24 |
25 | function distribute(address token) external;
26 |
27 | function setInvestFundRatio(uint value) external;
28 |
29 | function setGaugesRatio(uint value) external;
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/contracts/interfaces/IGauge.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IGauge {
6 |
7 | function veIds(address stakingToken, address account) external view returns (uint);
8 |
9 | function getReward(
10 | address stakingToken,
11 | address account,
12 | address[] memory tokens
13 | ) external;
14 |
15 | function getAllRewards(
16 | address stakingToken,
17 | address account
18 | ) external;
19 |
20 | function getAllRewardsForTokens(
21 | address[] memory stakingTokens,
22 | address account
23 | ) external;
24 |
25 | function attachVe(address stakingToken, address account, uint veId) external;
26 |
27 | function detachVe(address stakingToken, address account, uint veId) external;
28 |
29 | function handleBalanceChange(address account) external;
30 |
31 | function notifyRewardAmount(address stakingToken, address token, uint amount) external;
32 |
33 | function addStakingToken(address token) external;
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/contracts/interfaces/IMultiPool.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IMultiPool {
6 |
7 | function totalSupply(address stakingToken) external view returns (uint);
8 |
9 | function derivedSupply(address stakingToken) external view returns (uint);
10 |
11 | function derivedBalances(address stakingToken, address account) external view returns (uint);
12 |
13 | function balanceOf(address stakingToken, address account) external view returns (uint);
14 |
15 | function rewardTokens(address stakingToken, uint id) external view returns (address);
16 |
17 | function isRewardToken(address stakingToken, address token) external view returns (bool);
18 |
19 | function rewardTokensLength(address stakingToken) external view returns (uint);
20 |
21 | function derivedBalance(address stakingToken, address account) external view returns (uint);
22 |
23 | function left(address stakingToken, address token) external view returns (uint);
24 |
25 | function earned(address stakingToken, address token, address account) external view returns (uint);
26 |
27 | function registerRewardToken(address stakingToken, address token) external;
28 |
29 | function removeRewardToken(address stakingToken, address token) external;
30 |
31 | function isStakeToken(address token) external view returns (bool);
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPlatformVoter.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./IVeVotable.sol";
6 |
7 | interface IPlatformVoter is IVeVotable {
8 |
9 | enum AttributeType {
10 | UNKNOWN,
11 | INVEST_FUND_RATIO,
12 | GAUGE_RATIO,
13 | STRATEGY_COMPOUND
14 | }
15 |
16 | struct Vote {
17 | AttributeType _type;
18 | address target;
19 | uint weight;
20 | uint weightedValue;
21 | uint timestamp;
22 | }
23 |
24 | function veVotesLength(uint veId) external view returns (uint);
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPriceOracle.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IPriceOracle {
6 |
7 | /// @notice Return asset price in USD, decimals 18
8 | function getAssetPrice(address asset) external view returns (uint256);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/contracts/interfaces/IProxyControlled.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IProxyControlled {
6 |
7 | function initProxy(address _logic) external;
8 |
9 | function upgrade(address _newImplementation) external;
10 |
11 | function implementation() external view returns (address);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/contracts/interfaces/ISplitter.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity 0.8.17;
3 |
4 | interface ISplitter {
5 |
6 | function init(address controller_, address _asset, address _vault) external;
7 |
8 | // *************** ACTIONS **************
9 |
10 | function withdrawAllToVault() external;
11 |
12 | function withdrawToVault(uint256 amount) external;
13 |
14 | function coverPossibleStrategyLoss(uint earned, uint lost) external;
15 |
16 | function doHardWork() external;
17 |
18 | function investAll() external;
19 |
20 | // **************** VIEWS ***************
21 |
22 | function asset() external view returns (address);
23 |
24 | function vault() external view returns (address);
25 |
26 | function totalAssets() external view returns (uint256);
27 |
28 | function isHardWorking() external view returns (bool);
29 |
30 | function strategies(uint i) external view returns (address);
31 |
32 | function strategiesLength() external view returns (uint);
33 |
34 | function HARDWORK_DELAY() external view returns (uint);
35 |
36 | function lastHardWorks(address strategy) external view returns (uint);
37 |
38 | function pausedStrategies(address strategy) external view returns (bool);
39 |
40 | function pauseInvesting(address strategy) external;
41 |
42 | function continueInvesting(address strategy, uint apr) external;
43 |
44 | function rebalance(uint percent, uint lossTolerance) external;
45 |
46 | function getStrategyCapacity(address strategy) external view returns (uint capacity);
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/contracts/interfaces/IStrategyStrict.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity 0.8.17;
3 |
4 | interface IStrategyStrict {
5 |
6 | function NAME() external view returns (string memory);
7 |
8 | function PLATFORM() external view returns (string memory);
9 |
10 | function STRATEGY_VERSION() external view returns (string memory);
11 |
12 | function asset() external view returns (address);
13 |
14 | function vault() external view returns (address);
15 |
16 | function compoundRatio() external view returns (uint);
17 |
18 | function totalAssets() external view returns (uint);
19 |
20 | /// @dev Usually, indicate that claimable rewards have reasonable amount.
21 | function isReadyToHardWork() external view returns (bool);
22 |
23 | function withdrawAllToVault() external;
24 |
25 | function withdrawToVault(uint amount) external;
26 |
27 | function investAll() external;
28 |
29 | function doHardWork() external returns (uint earned, uint lost);
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/contracts/interfaces/IStrategyV2.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity 0.8.17;
3 |
4 | interface IStrategyV2 {
5 |
6 | function NAME() external view returns (string memory);
7 |
8 | function strategySpecificName() external view returns (string memory);
9 |
10 | function PLATFORM() external view returns (string memory);
11 |
12 | function STRATEGY_VERSION() external view returns (string memory);
13 |
14 | function asset() external view returns (address);
15 |
16 | function splitter() external view returns (address);
17 |
18 | function compoundRatio() external view returns (uint);
19 |
20 | function totalAssets() external view returns (uint);
21 |
22 | /// @dev Usually, indicate that claimable rewards have reasonable amount.
23 | function isReadyToHardWork() external view returns (bool);
24 |
25 | /// @return strategyLoss Loss should be covered from Insurance
26 | function withdrawAllToSplitter() external returns (uint strategyLoss);
27 |
28 | /// @return strategyLoss Loss should be covered from Insurance
29 | function withdrawToSplitter(uint amount) external returns (uint strategyLoss);
30 |
31 | /// @notice Stakes everything the strategy holds into the reward pool.
32 | /// @param amount_ Amount transferred to the strategy balance just before calling this function
33 | /// @param updateTotalAssetsBeforeInvest_ Recalculate total assets amount before depositing.
34 | /// It can be false if we know exactly, that the amount is already actual.
35 | /// @return strategyLoss Loss should be covered from Insurance
36 | function investAll(
37 | uint amount_,
38 | bool updateTotalAssetsBeforeInvest_
39 | ) external returns (
40 | uint strategyLoss
41 | );
42 |
43 | function doHardWork() external returns (uint earned, uint lost);
44 |
45 | function setCompoundRatio(uint value) external;
46 |
47 | /// @notice Max amount that can be deposited to the strategy (its internal capacity), see SCB-593.
48 | /// 0 means no deposit is allowed at this moment
49 | function capacity() external view returns (uint);
50 |
51 | /// @notice {performanceFee}% of total profit is sent to the {performanceReceiver} before compounding
52 | function performanceReceiver() external view returns (address);
53 |
54 | /// @notice A percent of total profit that is sent to the {performanceReceiver} before compounding
55 | /// @dev use FEE_DENOMINATOR
56 | function performanceFee() external view returns (uint);
57 | }
58 |
--------------------------------------------------------------------------------
/contracts/interfaces/IStrategyV3.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity 0.8.17;
3 |
4 | import "./IStrategyV2.sol";
5 |
6 | interface IStrategyV3 is IStrategyV2 {
7 | struct BaseState {
8 | /// @dev Underlying asset
9 | address asset;
10 |
11 | /// @dev Linked splitter
12 | address splitter;
13 |
14 | /// @notice {performanceFee}% of total profit is sent to {performanceReceiver} before compounding
15 | /// @dev governance by default
16 | address performanceReceiver;
17 |
18 | /// @notice A percent of total profit that is sent to the {performanceReceiver} before compounding
19 | /// @dev {DEFAULT_PERFORMANCE_FEE} by default, FEE_DENOMINATOR is used
20 | uint performanceFee;
21 |
22 | /// @notice Ratio to split performance fee on toPerf + toInsurance, [0..100_000]
23 | /// 100_000 - send full amount toPerf, 0 - send full amount toInsurance.
24 | uint performanceFeeRatio;
25 |
26 | /// @dev Percent of profit for autocompound inside this strategy.
27 | uint compoundRatio;
28 |
29 | /// @dev Represent specific name for this strategy. Should include short strategy name and used assets. Uniq across the vault.
30 | string strategySpecificName;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/contracts/interfaces/ITetuLiquidator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface ITetuLiquidator {
6 |
7 | struct PoolData {
8 | address pool;
9 | address swapper;
10 | address tokenIn;
11 | address tokenOut;
12 | }
13 |
14 | function addLargestPools(PoolData[] memory _pools, bool rewrite) external;
15 |
16 | function addBlueChipsPools(PoolData[] memory _pools, bool rewrite) external;
17 |
18 | function getPrice(address tokenIn, address tokenOut, uint amount) external view returns (uint);
19 |
20 | function getPriceForRoute(PoolData[] memory route, uint amount) external view returns (uint);
21 |
22 | function isRouteExist(address tokenIn, address tokenOut) external view returns (bool);
23 |
24 | function buildRoute(
25 | address tokenIn,
26 | address tokenOut
27 | ) external view returns (PoolData[] memory route, string memory errorMessage);
28 |
29 | function liquidate(
30 | address tokenIn,
31 | address tokenOut,
32 | uint amount,
33 | uint slippage
34 | ) external;
35 |
36 | function liquidateWithRoute(
37 | PoolData[] memory route,
38 | uint amount,
39 | uint slippage
40 | ) external;
41 |
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/interfaces/ITetuVaultV2.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./IVaultInsurance.sol";
6 | import "./IERC20.sol";
7 | import "./ISplitter.sol";
8 |
9 | interface ITetuVaultV2 {
10 |
11 | function splitter() external view returns (ISplitter);
12 |
13 | function insurance() external view returns (IVaultInsurance);
14 |
15 | function depositFee() external view returns (uint);
16 |
17 | function withdrawFee() external view returns (uint);
18 |
19 | function init(
20 | address controller_,
21 | IERC20 _asset,
22 | string memory _name,
23 | string memory _symbol,
24 | address _gauge,
25 | uint _buffer
26 | ) external;
27 |
28 | function setSplitter(address _splitter) external;
29 |
30 | function coverLoss(uint amount) external;
31 |
32 | function initInsurance(IVaultInsurance _insurance) external;
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVaultInsurance.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IVaultInsurance {
6 |
7 | function init(address _vault, address _asset) external;
8 |
9 | function vault() external view returns (address);
10 |
11 | function asset() external view returns (address);
12 |
13 | function transferToVault(uint amount) external;
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVeDistributor.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IVeDistributor {
6 |
7 | function rewardToken() external view returns (address);
8 |
9 | function checkpoint() external;
10 |
11 | function checkpointTotalSupply() external;
12 |
13 | function claim(uint _tokenId) external returns (uint);
14 |
15 | function claimable(uint _tokenId) external view returns (uint);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVeDistributorV2.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./IVeDistributor.sol";
6 |
7 | interface IVeDistributorV2 is IVeDistributor {
8 |
9 | function epoch() external view returns (uint);
10 |
11 | function lastPaidEpoch(uint veId) external view returns (uint);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVeTetu.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./IERC721Metadata.sol";
6 |
7 | interface IVeTetu is IERC721Metadata {
8 |
9 | enum DepositType {
10 | DEPOSIT_FOR_TYPE,
11 | CREATE_LOCK_TYPE,
12 | INCREASE_LOCK_AMOUNT,
13 | INCREASE_UNLOCK_TIME,
14 | MERGE_TYPE
15 | }
16 |
17 | struct Point {
18 | int128 bias;
19 | int128 slope; // # -dweight / dt
20 | uint ts;
21 | uint blk; // block
22 | }
23 | /* We cannot really do block numbers per se b/c slope is per time, not per block
24 | * and per block could be fairly bad b/c Ethereum changes blocktimes.
25 | * What we can do is to extrapolate ***At functions */
26 |
27 | function attachments(uint tokenId) external view returns (uint);
28 |
29 | function lockedAmounts(uint veId, address stakingToken) external view returns (uint);
30 |
31 | function lockedDerivedAmount(uint veId) external view returns (uint);
32 |
33 | function lockedEnd(uint veId) external view returns (uint);
34 |
35 | // function voted(uint tokenId) external view returns (uint);
36 | function isVoted(uint tokenId) external view returns (bool);
37 |
38 | function tokens(uint idx) external view returns (address);
39 |
40 | function balanceOfNFT(uint) external view returns (uint);
41 |
42 | function isApprovedOrOwner(address, uint) external view returns (bool);
43 |
44 | function createLockFor(address _token, uint _value, uint _lockDuration, address _to) external returns (uint);
45 |
46 | function userPointEpoch(uint tokenId) external view returns (uint);
47 |
48 | function epoch() external view returns (uint);
49 |
50 | function checkpoint() external;
51 |
52 | function increaseAmount(address _token, uint _tokenId, uint _value) external;
53 |
54 | function attachToken(uint tokenId) external;
55 |
56 | function detachToken(uint tokenId) external;
57 |
58 | function voting(uint tokenId) external;
59 |
60 | function abstain(uint tokenId) external;
61 |
62 | function totalSupply() external view returns (uint);
63 | }
64 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVeVotable.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IVeVotable {
6 |
7 | function isVotesExist(uint veId) external view returns (bool);
8 |
9 | function detachTokenFromAll(uint tokenId, address owner) external;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/contracts/interfaces/IVoter.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./IVeVotable.sol";
6 |
7 | interface IVoter is IVeVotable {
8 |
9 | function ve() external view returns (address);
10 |
11 | function attachTokenToGauge(address stakingToken, uint _tokenId, address account) external;
12 |
13 | function detachTokenFromGauge(address stakingToken, uint _tokenId, address account) external;
14 |
15 | function distribute(address stakingToken) external;
16 |
17 | function distributeAll() external;
18 |
19 | function notifyRewardAmount(uint amount) external;
20 |
21 | function votedVaultsLength(uint veId) external view returns (uint);
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/contracts/lib/Base64.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | /// @title Base64
6 | /// @notice Provides a function for encoding some bytes in base64
7 | /// @author Brecht Devos
8 | library Base64 {
9 | bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10 |
11 | /// @notice Encodes some bytes to the base64 representation
12 | function encode(bytes memory data) internal pure returns (string memory) {
13 | uint len = data.length;
14 | if (len == 0) return "";
15 |
16 | // multiply by 4/3 rounded up
17 | uint encodedLen = 4 * ((len + 2) / 3);
18 |
19 | // Add some extra buffer at the end
20 | bytes memory result = new bytes(encodedLen + 32);
21 |
22 | bytes memory table = TABLE;
23 |
24 | assembly {
25 | let tablePtr := add(table, 1)
26 | let resultPtr := add(result, 32)
27 |
28 | for {
29 | let i := 0
30 | } lt(i, len) {
31 |
32 | } {
33 | i := add(i, 3)
34 | let input := and(mload(add(data, i)), 0xffffff)
35 |
36 | let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
37 | out := shl(8, out)
38 | out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
39 | out := shl(8, out)
40 | out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
41 | out := shl(8, out)
42 | out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
43 | out := shl(224, out)
44 |
45 | mstore(resultPtr, out)
46 |
47 | resultPtr := add(resultPtr, 4)
48 | }
49 |
50 | switch mod(len, 3)
51 | case 1 {
52 | mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
53 | }
54 | case 2 {
55 | mstore(sub(resultPtr, 1), shl(248, 0x3d))
56 | }
57 |
58 | mstore(result, encodedLen)
59 | }
60 |
61 | return string(result);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/contracts/lib/InterfaceIds.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | /// @title Library for interface IDs
6 | /// @author bogdoslav
7 | library InterfaceIds {
8 |
9 | /// @notice Version of the contract
10 | /// @dev Should be incremented when contract changed
11 | string public constant INTERFACE_IDS_LIB_VERSION = "1.0.1";
12 |
13 | /// default notation:
14 | /// bytes4 public constant I_VOTER = type(IVoter).interfaceId;
15 |
16 | /// As type({Interface}).interfaceId can be changed,
17 | /// when some functions changed at the interface,
18 | /// so used hardcoded interface identifiers
19 |
20 | bytes4 public constant I_VOTER = bytes4(keccak256("IVoter"));
21 | bytes4 public constant I_BRIBE = bytes4(keccak256("IBribe"));
22 | bytes4 public constant I_GAUGE = bytes4(keccak256("IGauge"));
23 | bytes4 public constant I_VE_TETU = bytes4(keccak256("IVeTetu"));
24 | bytes4 public constant I_SPLITTER = bytes4(keccak256("ISplitter"));
25 | bytes4 public constant I_FORWARDER = bytes4(keccak256("IForwarder"));
26 | bytes4 public constant I_MULTI_POOL = bytes4(keccak256("IMultiPool"));
27 | bytes4 public constant I_CONTROLLER = bytes4(keccak256("IController"));
28 | bytes4 public constant I_TETU_ERC165 = bytes4(keccak256("ITetuERC165"));
29 | bytes4 public constant I_STRATEGY_V2 = bytes4(keccak256("IStrategyV2"));
30 | bytes4 public constant I_STRATEGY_V3 = bytes4(keccak256("IStrategyV3"));
31 | bytes4 public constant I_CONTROLLABLE = bytes4(keccak256("IControllable"));
32 | bytes4 public constant I_TETU_VAULT_V2 = bytes4(keccak256("ITetuVaultV2"));
33 | bytes4 public constant I_PLATFORM_VOTER = bytes4(keccak256("IPlatformVoter"));
34 | bytes4 public constant I_VE_DISTRIBUTOR = bytes4(keccak256("IVeDistributor"));
35 | bytes4 public constant I_TETU_CONVERTER = bytes4(keccak256("ITetuConverter"));
36 | bytes4 public constant I_VAULT_INSURANCE = bytes4(keccak256("IVaultInsurance"));
37 | bytes4 public constant I_STRATEGY_STRICT = bytes4(keccak256("IStrategyStrict"));
38 | bytes4 public constant I_ERC4626 = bytes4(keccak256("IERC4626"));
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/contracts/lib/StringLib.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 |
6 | library StringLib {
7 |
8 | /// @dev Inspired by OraclizeAPI's implementation - MIT license
9 | /// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
10 | function toString(uint value) external pure returns (string memory) {
11 | return _toString(value);
12 | }
13 |
14 | function _toString(uint value) internal pure returns (string memory) {
15 | if (value == 0) {
16 | return "0";
17 | }
18 | uint temp = value;
19 | uint digits;
20 | while (temp != 0) {
21 | digits++;
22 | temp /= 10;
23 | }
24 | bytes memory buffer = new bytes(digits);
25 | while (value != 0) {
26 | digits -= 1;
27 | buffer[digits] = bytes1(uint8(48 + uint(value % 10)));
28 | value /= 10;
29 | }
30 | return string(buffer);
31 | }
32 |
33 | function toAsciiString(address x) external pure returns (string memory) {
34 | return _toAsciiString(x);
35 | }
36 |
37 | function _toAsciiString(address x) internal pure returns (string memory) {
38 | bytes memory s = new bytes(40);
39 | for (uint i = 0; i < 20; i++) {
40 | bytes1 b = bytes1(uint8(uint(uint160(x)) / (2 ** (8 * (19 - i)))));
41 | bytes1 hi = bytes1(uint8(b) / 16);
42 | bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
43 | s[2 * i] = _char(hi);
44 | s[2 * i + 1] = _char(lo);
45 | }
46 | return string(s);
47 | }
48 |
49 | function char(bytes1 b) external pure returns (bytes1 c) {
50 | return _char(b);
51 | }
52 |
53 | function _char(bytes1 b) internal pure returns (bytes1 c) {
54 | if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
55 | else return bytes1(uint8(b) + 0x57);
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/Context.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | /**
7 | * @dev Provides information about the current execution context, including the
8 | * sender of the transaction and its data. While these are generally available
9 | * via msg.sender and msg.data, they should not be accessed in such a direct
10 | * manner, since when dealing with meta-transactions the account sending and
11 | * paying for execution may not be the actual sender (as far as an application
12 | * is concerned).
13 | *
14 | * This contract is only required for intermediate, library-like contracts.
15 | */
16 | abstract contract Context {
17 | function _msgSender() internal view virtual returns (address) {
18 | return msg.sender;
19 | }
20 |
21 | function _msgData() internal view virtual returns (bytes calldata) {
22 | return msg.data;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/ContextUpgradeable.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
3 |
4 | pragma solidity 0.8.17;
5 | import "./Initializable.sol";
6 |
7 | /**
8 | * https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/release-v4.6/contracts/utils/ContextUpgradeable.sol
9 | * @dev Provides information about the current execution context, including the
10 | * sender of the transaction and its data. While these are generally available
11 | * via msg.sender and msg.data, they should not be accessed in such a direct
12 | * manner, since when dealing with meta-transactions the account sending and
13 | * paying for execution may not be the actual sender (as far as an application
14 | * is concerned).
15 | *
16 | * This contract is only required for intermediate, library-like contracts.
17 | */
18 | abstract contract ContextUpgradeable is Initializable {
19 | function __Context_init() internal onlyInitializing {
20 | }
21 |
22 | function __Context_init_unchained() internal onlyInitializing {
23 | }
24 | function _msgSender() internal view virtual returns (address) {
25 | return msg.sender;
26 | }
27 |
28 | function _msgData() internal view virtual returns (bytes calldata) {
29 | return msg.data;
30 | }
31 |
32 | /**
33 | * @dev This empty reserved space is put in place to allow future versions to add new
34 | * variables without shifting down storage in the inheritance chain.
35 | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
36 | */
37 | uint[50] private __gap;
38 | }
39 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/Counters.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | /**
7 | * @title Counters
8 | * @author Matt Condon (@shrugs)
9 | * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
10 | * of elements in a mapping, issuing ERC721 ids, or counting request ids.
11 | *
12 | * Include with `using Counters for Counters.Counter;`
13 | */
14 | library Counters {
15 | struct Counter {
16 | // This variable should never be directly accessed by users of the library: interactions must be restricted to
17 | // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
18 | // this feature: see https://github.com/ethereum/solidity/issues/4637
19 | uint256 _value; // default: 0
20 | }
21 |
22 | function current(Counter storage counter) internal view returns (uint256) {
23 | return counter._value;
24 | }
25 |
26 | function increment(Counter storage counter) internal {
27 | unchecked {
28 | counter._value += 1;
29 | }
30 | }
31 |
32 | function decrement(Counter storage counter) internal {
33 | uint256 value = counter._value;
34 | require(value > 0, "Counter: decrement overflow");
35 | unchecked {
36 | counter._value = value - 1;
37 | }
38 | }
39 |
40 | function reset(Counter storage counter) internal {
41 | counter._value = 0;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/CountersUpgradeable.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | /**
7 | * @title Counters
8 | * @author Matt Condon (@shrugs)
9 | * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
10 | * of elements in a mapping, issuing ERC721 ids, or counting request ids.
11 | *
12 | * Include with `using Counters for Counters.Counter;`
13 | */
14 | library CountersUpgradeable {
15 | struct Counter {
16 | // This variable should never be directly accessed by users of the library: interactions must be restricted to
17 | // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
18 | // this feature: see https://github.com/ethereum/solidity/issues/4637
19 | uint256 _value; // default: 0
20 | }
21 |
22 | function current(Counter storage counter) internal view returns (uint256) {
23 | return counter._value;
24 | }
25 |
26 | function increment(Counter storage counter) internal {
27 | unchecked {
28 | counter._value += 1;
29 | }
30 | }
31 |
32 | function decrement(Counter storage counter) internal {
33 | uint256 value = counter._value;
34 | require(value > 0, "Counter: decrement overflow");
35 | unchecked {
36 | counter._value = value - 1;
37 | }
38 | }
39 |
40 | function reset(Counter storage counter) internal {
41 | counter._value = 0;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/ERC165.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | import "../interfaces/IERC165.sol";
7 |
8 | /**
9 | * @dev Implementation of the {IERC165} interface.
10 | *
11 | * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
12 | * for the additional interface id that will be supported. For example:
13 | *
14 | * ```solidity
15 | * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
16 | * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
17 | * }
18 | * ```
19 | *
20 | * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
21 | */
22 | abstract contract ERC165 is IERC165 {
23 | /**
24 | * @dev See {IERC165-supportsInterface}.
25 | */
26 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
27 | return interfaceId == type(IERC165).interfaceId;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/ERC20Permit.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | import "../interfaces/IERC20Permit.sol";
7 | import "./ERC20.sol";
8 | import "./ECDSA.sol";
9 | import "./EIP712.sol";
10 | import "./Counters.sol";
11 |
12 | /**
13 | * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
14 | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
15 | *
16 | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
17 | * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
18 | * need to send a transaction, and thus is not required to hold Ether at all.
19 | *
20 | * _Available since v3.4._
21 | */
22 | abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
23 | using Counters for Counters.Counter;
24 |
25 | mapping(address => Counters.Counter) private _nonces;
26 |
27 | // solhint-disable-next-line var-name-mixedcase
28 | bytes32 private constant _PERMIT_TYPEHASH =
29 | keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
30 | /**
31 | * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
32 | * However, to ensure consistency with the upgradeable transpiler, we will continue
33 | * to reserve a slot.
34 | * @custom:oz-renamed-from _PERMIT_TYPEHASH
35 | */
36 | // solhint-disable-next-line var-name-mixedcase
37 | bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
38 |
39 | /**
40 | * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
41 | *
42 | * It's a good idea to use the same `name` that is defined as the ERC20 token name.
43 | */
44 | constructor(string memory name) EIP712(name, "1") {}
45 |
46 | /**
47 | * @dev See {IERC20Permit-permit}.
48 | */
49 | function permit(
50 | address owner,
51 | address spender,
52 | uint256 value,
53 | uint256 deadline,
54 | uint8 v,
55 | bytes32 r,
56 | bytes32 s
57 | ) public virtual override {
58 | require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
59 |
60 | bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
61 |
62 | bytes32 hash = _hashTypedDataV4(structHash);
63 |
64 | address signer = ECDSA.recover(hash, v, r, s);
65 | require(signer == owner, "ERC20Permit: invalid signature");
66 |
67 | _approve(owner, spender, value);
68 | }
69 |
70 | /**
71 | * @dev See {IERC20Permit-nonces}.
72 | */
73 | function nonces(address owner) public view virtual override returns (uint256) {
74 | return _nonces[owner].current();
75 | }
76 |
77 | /**
78 | * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
79 | */
80 | // solhint-disable-next-line func-name-mixedcase
81 | function DOMAIN_SEPARATOR() external view override returns (bytes32) {
82 | return _domainSeparatorV4();
83 | }
84 |
85 | /**
86 | * @dev "Consume a nonce": return the current value and increment.
87 | *
88 | * _Available since v4.1._
89 | */
90 | function _useNonce(address owner) internal virtual returns (uint256 current) {
91 | Counters.Counter storage nonce = _nonces[owner];
92 | current = nonce.current();
93 | nonce.increment();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/Proxy.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | /**
7 | * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
8 | * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
9 | * be specified by overriding the virtual {_implementation} function.
10 | *
11 | * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
12 | * different contract through the {_delegate} function.
13 | *
14 | * The success and return data of the delegated call will be returned back to the caller of the proxy.
15 | */
16 | abstract contract Proxy {
17 | /**
18 | * @dev Delegates the current call to `implementation`.
19 | *
20 | * This function does not return to its internal call site, it will return directly to the external caller.
21 | */
22 | function _delegate(address implementation) internal virtual {
23 | assembly {
24 | // Copy msg.data. We take full control of memory in this inline assembly
25 | // block because it will not return to Solidity code. We overwrite the
26 | // Solidity scratch pad at memory position 0.
27 | calldatacopy(0, 0, calldatasize())
28 |
29 | // Call the implementation.
30 | // out and outsize are 0 because we don't know the size yet.
31 | let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
32 |
33 | // Copy the returned data.
34 | returndatacopy(0, 0, returndatasize())
35 |
36 | switch result
37 | // delegatecall returns 0 on error.
38 | case 0 {
39 | revert(0, returndatasize())
40 | }
41 | default {
42 | return (0, returndatasize())
43 | }
44 | }
45 | }
46 |
47 | /**
48 | * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
49 | * and {_fallback} should delegate.
50 | */
51 | function _implementation() internal view virtual returns (address);
52 |
53 | /**
54 | * @dev Delegates the current call to the address returned by `_implementation()`.
55 | *
56 | * This function does not return to its internal call site, it will return directly to the external caller.
57 | */
58 | function _fallback() internal virtual {
59 | _beforeFallback();
60 | _delegate(_implementation());
61 | }
62 |
63 | /**
64 | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
65 | * function in the contract matches the call data.
66 | */
67 | fallback() external payable virtual {
68 | _fallback();
69 | }
70 |
71 | /**
72 | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
73 | * is empty.
74 | */
75 | receive() external payable virtual {
76 | _fallback();
77 | }
78 |
79 | /**
80 | * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
81 | * call, or as part of the Solidity `fallback` or `receive` functions.
82 | *
83 | * If overridden should call `super._beforeFallback()`.
84 | */
85 | function _beforeFallback() internal virtual {}
86 | }
87 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/ReentrancyGuard.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
3 |
4 | pragma solidity 0.8.17;
5 |
6 | /**
7 | * @dev Contract module that helps prevent reentrant calls to a function.
8 | *
9 | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
10 | * available, which can be applied to functions to make sure there are no nested
11 | * (reentrant) calls to them.
12 | *
13 | * Note that because there is a single `nonReentrant` guard, functions marked as
14 | * `nonReentrant` may not call one another. This can be worked around by making
15 | * those functions `private`, and then adding `external` `nonReentrant` entry
16 | * points to them.
17 | *
18 | * TIP: If you would like to learn more about reentrancy and alternative ways
19 | * to protect against it, check out our blog post
20 | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
21 | */
22 | abstract contract ReentrancyGuard {
23 | // Booleans are more expensive than uint256 or any type that takes up a full
24 | // word because each write operation emits an extra SLOAD to first read the
25 | // slot's contents, replace the bits taken up by the boolean, and then write
26 | // back. This is the compiler's defense against contract upgrades and
27 | // pointer aliasing, and it cannot be disabled.
28 |
29 | // The values being non-zero value makes deployment a bit more expensive,
30 | // but in exchange the refund on every call to nonReentrant will be lower in
31 | // amount. Since refunds are capped to a percentage of the total
32 | // transaction's gas, it is best to keep them low in cases like this one, to
33 | // increase the likelihood of the full refund coming into effect.
34 | uint256 private constant _NOT_ENTERED = 1;
35 | uint256 private constant _ENTERED = 2;
36 |
37 | uint256 private _status;
38 |
39 | constructor() {
40 | _status = _NOT_ENTERED;
41 | }
42 |
43 | /**
44 | * @dev Prevents a contract from calling itself, directly or indirectly.
45 | * Calling a `nonReentrant` function from another `nonReentrant`
46 | * function is not supported. It is possible to prevent this from happening
47 | * by making the `nonReentrant` function external, and making it call a
48 | * `private` function that does the actual work.
49 | */
50 | modifier nonReentrant() {
51 | _nonReentrantBefore();
52 | _;
53 | _nonReentrantAfter();
54 | }
55 |
56 | function _nonReentrantBefore() private {
57 | // On the first call to nonReentrant, _status will be _NOT_ENTERED
58 | require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
59 |
60 | // Any calls to nonReentrant after this point will fail
61 | _status = _ENTERED;
62 | }
63 |
64 | function _nonReentrantAfter() private {
65 | // By storing the original value once again, a refund is triggered (see
66 | // https://eips.ethereum.org/EIPS/eip-2200)
67 | _status = _NOT_ENTERED;
68 | }
69 |
70 | /**
71 | * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
72 | * `nonReentrant` function in the call stack.
73 | */
74 | function _reentrancyGuardEntered() internal view returns (bool) {
75 | return _status == _ENTERED;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/contracts/openzeppelin/Strings.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
3 |
4 | pragma solidity ^0.8.0;
5 |
6 | import "./Math.sol";
7 |
8 | /**
9 | * @dev String operations.
10 | */
11 | library Strings {
12 | bytes16 private constant _SYMBOLS = "0123456789abcdef";
13 | uint8 private constant _ADDRESS_LENGTH = 20;
14 |
15 | /**
16 | * @dev Converts a `uint256` to its ASCII `string` decimal representation.
17 | */
18 | function toString(uint256 value) internal pure returns (string memory) {
19 | unchecked {
20 | uint256 length = Math.log10(value) + 1;
21 | string memory buffer = new string(length);
22 | uint256 ptr;
23 | /// @solidity memory-safe-assembly
24 | assembly {
25 | ptr := add(buffer, add(32, length))
26 | }
27 | while (true) {
28 | ptr--;
29 | /// @solidity memory-safe-assembly
30 | assembly {
31 | mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
32 | }
33 | value /= 10;
34 | if (value == 0) break;
35 | }
36 | return buffer;
37 | }
38 | }
39 |
40 | /**
41 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
42 | */
43 | function toHexString(uint256 value) internal pure returns (string memory) {
44 | unchecked {
45 | return toHexString(value, Math.log256(value) + 1);
46 | }
47 | }
48 |
49 | /**
50 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
51 | */
52 | function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
53 | bytes memory buffer = new bytes(2 * length + 2);
54 | buffer[0] = "0";
55 | buffer[1] = "x";
56 | for (uint256 i = 2 * length + 1; i > 1; --i) {
57 | buffer[i] = _SYMBOLS[value & 0xf];
58 | value >>= 4;
59 | }
60 | require(value == 0, "Strings: hex length insufficient");
61 | return string(buffer);
62 | }
63 |
64 | /**
65 | * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
66 | */
67 | function toHexString(address addr) internal pure returns (string memory) {
68 | return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/contracts/proxy/ProxyControlled.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/IControllable.sol";
6 | import "../interfaces/IProxyControlled.sol";
7 | import "./UpgradeableProxy.sol";
8 | import "../interfaces/IERC165.sol";
9 | import "../lib/InterfaceIds.sol";
10 |
11 | /// @title EIP1967 Upgradable proxy implementation.
12 | /// @dev Only Controller has access and should implement time-lock for upgrade action.
13 | /// @author belbix
14 | contract ProxyControlled is UpgradeableProxy, IProxyControlled {
15 |
16 | /// @notice Version of the contract
17 | /// @dev Should be incremented when contract changed
18 | string public constant PROXY_CONTROLLED_VERSION = "1.0.1";
19 |
20 | /// @dev Initialize proxy implementation. Need to call after deploy new proxy.
21 | function initProxy(address _logic) external override {
22 | //make sure that given logic is controllable and not inited
23 | require(IERC165(_logic).supportsInterface(InterfaceIds.I_CONTROLLABLE), "Proxy: Wrong implementation");
24 | _init(_logic);
25 | }
26 |
27 | /// @notice Upgrade contract logic
28 | /// @dev Upgrade allowed only for Controller and should be done only after time-lock period
29 | /// @param _newImplementation Implementation address
30 | function upgrade(address _newImplementation) external override {
31 | require(IERC165(_newImplementation).supportsInterface(InterfaceIds.I_CONTROLLABLE), "Proxy: Wrong implementation");
32 | require(IControllable(address(this)).isController(msg.sender), "Proxy: Forbidden");
33 | IControllable(address(this)).increaseRevision(_implementation());
34 | _upgradeTo(_newImplementation);
35 | // the new contract must have the same ABI and you must have the power to change it again
36 | require(IControllable(address(this)).isController(msg.sender), "Proxy: Wrong implementation");
37 | }
38 |
39 | /// @notice Return current logic implementation
40 | function implementation() external override view returns (address) {
41 | return _implementation();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/proxy/UpgradeableProxy.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../openzeppelin/Proxy.sol";
6 | import "../openzeppelin/Address.sol";
7 |
8 | /// @title OpenZeppelin https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/proxy/UpgradeableProxy.sol
9 | /// @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
10 | /// implementation address that can be changed. This address is stored in storage in the location specified by
11 | /// https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
12 | /// implementation behind the proxy.
13 | /// Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
14 | /// {TransparentUpgradeableProxy}.
15 | abstract contract UpgradeableProxy is Proxy {
16 |
17 | /// @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
18 | /// If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
19 | /// function call, and allows initializating the storage of the proxy like a Solidity constructor.
20 | constructor() payable {
21 | assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
22 | }
23 |
24 | /// @dev Emitted when the implementation is upgraded.
25 | event Upgraded(address indexed implementation);
26 |
27 | ///@dev Storage slot with the address of the current implementation.
28 | /// This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
29 | /// validated in the constructor.
30 | bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
31 |
32 | /// @dev Post deploy initialisation for compatability with EIP-1167 factory
33 | function _init(address _logic) internal {
34 | require(_implementation() == address(0), "Already inited");
35 | _setImplementation(_logic);
36 | }
37 |
38 | /// @dev Returns the current implementation address.
39 | function _implementation() internal view virtual override returns (address impl) {
40 | bytes32 slot = _IMPLEMENTATION_SLOT;
41 | // solhint-disable-next-line no-inline-assembly
42 | assembly {
43 | impl := sload(slot)
44 | }
45 | }
46 |
47 | /// @dev Upgrades the proxy to a new implementation.
48 | /// Emits an {Upgraded} event.
49 | function _upgradeTo(address newImplementation) internal virtual {
50 | _setImplementation(newImplementation);
51 | emit Upgraded(newImplementation);
52 | }
53 |
54 | /// @dev Stores a new address in the EIP1967 implementation slot.
55 | function _setImplementation(address newImplementation) private {
56 | require(Address.isContract(newImplementation), "UpgradeableProxy: new implementation is not a contract");
57 |
58 | bytes32 slot = _IMPLEMENTATION_SLOT;
59 |
60 | // solhint-disable-next-line no-inline-assembly
61 | assembly {
62 | sstore(slot, newImplementation)
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/contracts/test/Base64Test.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../lib/Base64.sol";
6 |
7 | contract Base64Test {
8 |
9 | function encode(bytes memory data) external pure returns (string memory) {
10 | return Base64.encode(data);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/contracts/test/ControllableTest.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 |
7 | contract ControllableTest is ControllableV3 {
8 |
9 | uint private _variable;
10 |
11 | function init(address controller_) external initializer {
12 | ControllableV3.__Controllable_init(controller_);
13 | _variable = 333;
14 | }
15 |
16 | function increase() external {
17 | this.increaseRevision(address(this));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/contracts/test/ControllerMinimal.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../tools/TetuERC165.sol";
6 | import "../interfaces/IProxyControlled.sol";
7 | import "../interfaces/IController.sol";
8 | import "../lib/InterfaceIds.sol";
9 |
10 | contract ControllerMinimal is TetuERC165, IController {
11 |
12 | address public override governance;
13 | address public override voter;
14 | address public override liquidator;
15 | address public override forwarder;
16 | address public override investFund;
17 | address public veDistributor;
18 | address public override platformVoter;
19 | address[] public override vaults;
20 | mapping(address => bool) public operators;
21 |
22 | constructor (address governance_) {
23 | governance = governance_;
24 | operators[governance_] = true;
25 | }
26 |
27 | function setVoter(address _voter) external {
28 | voter = _voter;
29 | }
30 |
31 | function setPlatformVoter(address _voter) external {
32 | platformVoter = _voter;
33 | }
34 |
35 | function setLiquidator(address value) external {
36 | liquidator = value;
37 | }
38 |
39 | function setInvestFund(address value) external {
40 | investFund = value;
41 | }
42 |
43 | function setForwarder(address value) external {
44 | forwarder = value;
45 | }
46 |
47 | function setVeDistributor(address value) external {
48 | veDistributor = value;
49 | }
50 |
51 | function addVault(address vault) external {
52 | vaults.push(vault);
53 | }
54 |
55 | function addOperator(address operator) external {
56 | operators[operator] = true;
57 | }
58 |
59 | function updateProxies(address[] memory proxies, address[] memory newLogics) external {
60 | require(proxies.length == newLogics.length, "Wrong arrays");
61 | for (uint i; i < proxies.length; i++) {
62 | IProxyControlled(proxies[i]).upgrade(newLogics[i]);
63 | }
64 | }
65 |
66 | function vaultsList() external view override returns (address[] memory) {
67 | return vaults;
68 | }
69 |
70 | function vaultsListLength() external override view returns (uint) {
71 | return vaults.length;
72 | }
73 |
74 | function isValidVault(address _vault) external view override returns (bool) {
75 | for (uint i; i < vaults.length; i++) {
76 | if (_vault == vaults[i]) {
77 | return true;
78 | }
79 | }
80 | return false;
81 | }
82 |
83 | function isOperator(address _adr) external view override returns (bool) {
84 | return operators[_adr];
85 | }
86 |
87 | /// @dev See {IERC165-supportsInterface}.
88 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
89 | return interfaceId == InterfaceIds.I_CONTROLLER || super.supportsInterface(interfaceId);
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/contracts/test/IMockToken.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface IMockToken {
6 |
7 | function decimals() external view returns (uint8);
8 |
9 | function mint(address to, uint amount) external;
10 |
11 | function burn(address from, uint amount) external;
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/test/MockBribe.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 |
7 | contract MockBribe is ControllableV3 {
8 |
9 | uint public epoch;
10 | mapping(address => mapping(address => bool)) internal rewardTokens;
11 |
12 | function init(address controller_) external initializer {
13 | __Controllable_init(controller_);
14 | }
15 |
16 | function isRewardToken(address st, address rt) external view returns (bool) {
17 | return rewardTokens[st][rt];
18 | }
19 |
20 | function registerRewardToken(address st, address rt) external {
21 | rewardTokens[st][rt] = true;
22 | }
23 |
24 | function notifyRewardAmount(address, address token, uint amount) external {
25 | IERC20(token).transferFrom(msg.sender, address(this), amount);
26 | }
27 |
28 | function notifyForNextEpoch(address, address token, uint amount) external {
29 | IERC20(token).transferFrom(msg.sender, address(this), amount);
30 | }
31 |
32 | function notifyDelayedRewards(address, address, uint) external {
33 | // noop
34 | }
35 |
36 | /// @dev See {IERC165-supportsInterface}.
37 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
38 | return interfaceId == InterfaceIds.I_BRIBE || super.supportsInterface(interfaceId);
39 | }
40 |
41 | function increaseEpoch() external {
42 | epoch++;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/contracts/test/MockForwarder.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../lib/InterfaceIds.sol";
6 |
7 | contract MockForwarder {
8 |
9 | function registerIncome(
10 | address[] memory,
11 | uint[] memory,
12 | address,
13 | bool
14 | ) external {
15 | // noop
16 | }
17 |
18 | function distributeAll(address) external {
19 | // noop
20 | }
21 |
22 | function distribute(address) external pure {
23 | // noop
24 | }
25 |
26 | /// @dev See {IERC165-supportsInterface}.
27 | function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
28 | return interfaceId == InterfaceIds.I_FORWARDER;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/contracts/test/MockGauge.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 |
7 | contract MockGauge is ControllableV3 {
8 |
9 | function init(address controller_) external initializer {
10 | __Controllable_init(controller_);
11 | }
12 |
13 | function handleBalanceChange(address) external {
14 | // noop
15 | }
16 |
17 | /// @dev See {IERC165-supportsInterface}.
18 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
19 | return interfaceId == InterfaceIds.I_GAUGE || super.supportsInterface(interfaceId);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/contracts/test/MockLiquidator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/ITetuLiquidator.sol";
6 | import "../interfaces/IERC20.sol";
7 |
8 | contract MockLiquidator is ITetuLiquidator {
9 |
10 | uint internal price = 100_000 * 1e18;
11 | string internal error = "";
12 | uint internal routeLength = 1;
13 | bool internal useTokensToCalculatePrice;
14 |
15 | function setPrice(uint value) external {
16 | price = value;
17 | }
18 |
19 | function setUseTokensToCalculatePrice(bool value) external {
20 | useTokensToCalculatePrice = value;
21 | }
22 |
23 | function setError(string memory value) external {
24 | error = value;
25 | }
26 |
27 | function setRouteLength(uint value) external {
28 | routeLength = value;
29 | }
30 |
31 | function getPrice(address, address, uint tokens) external view override returns (uint) {
32 | return useTokensToCalculatePrice
33 | ? price * tokens
34 | : price;
35 | }
36 |
37 | function getPriceForRoute(PoolData[] memory, uint) external view override returns (uint) {
38 | return price;
39 | }
40 |
41 | function isRouteExist(address, address) external pure override returns (bool) {
42 | return true;
43 | }
44 |
45 | function buildRoute(
46 | address tokenIn,
47 | address tokenOut
48 | ) external view override returns (PoolData[] memory route, string memory errorMessage) {
49 | if (routeLength == 1) {
50 | route = new PoolData[](1);
51 | route[0].tokenIn = tokenIn;
52 | route[0].tokenOut = tokenOut;
53 | } else {
54 | route = new PoolData[](0);
55 | }
56 | return (route, error);
57 | }
58 |
59 | function liquidate(
60 | address,
61 | address tokenOut,
62 | uint amount,
63 | uint
64 | ) external override {
65 | IERC20(tokenOut).transfer(msg.sender, amount);
66 | }
67 |
68 | function liquidateWithRoute(
69 | PoolData[] memory route,
70 | uint amount,
71 | uint
72 | ) external override {
73 | IERC20(route[0].tokenIn).transferFrom(msg.sender, address(this), amount);
74 | IERC20(route[route.length - 1].tokenOut).transfer(msg.sender, amount);
75 | }
76 |
77 | function addLargestPools(PoolData[] memory /*_pools*/, bool /*rewrite*/) external pure {
78 | // noop
79 | }
80 |
81 | function addBlueChipsPools(PoolData[] memory /*_pools*/, bool /*rewrite*/) external pure {
82 | // noop
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/contracts/test/MockPawnshop.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/IERC721.sol";
6 | import "../interfaces/IVeTetu.sol";
7 | import "../interfaces/IERC721Receiver.sol";
8 |
9 | contract MockPawnshop is IERC721Receiver{
10 |
11 | function transfer(address nft, address from, address to, uint id) external {
12 | IERC721(nft).safeTransferFrom(from, to, id);
13 | }
14 |
15 | function transferAndGetBalance(address nft, address from, address to, uint id) external returns (uint){
16 | IERC721(nft).safeTransferFrom(from, to, id);
17 | return IVeTetu(nft).balanceOfNFT(id);
18 | }
19 |
20 | function doubleTransfer(address nft, address from, address to, uint id) external {
21 | IERC721(nft).safeTransferFrom(from, to, id);
22 | IERC721(nft).safeTransferFrom(to, from, id);
23 | IERC721(nft).safeTransferFrom(from, to, id);
24 | }
25 |
26 | function veFlashTransfer(address ve, uint tokenId) external {
27 | IERC721(ve).safeTransferFrom(msg.sender, address(this), tokenId);
28 | require(IVeTetu(ve).balanceOfNFT(tokenId) == 0, "not zero balance");
29 | IVeTetu(ve).checkpoint();
30 | IVeTetu(ve).checkpoint();
31 | IVeTetu(ve).checkpoint();
32 | IVeTetu(ve).checkpoint();
33 | IERC721(ve).safeTransferFrom(address(this), msg.sender, tokenId);
34 | }
35 |
36 | function onERC721Received(
37 | address,
38 | address,
39 | uint256,
40 | bytes memory
41 | ) public virtual override returns (bytes4) {
42 | return this.onERC721Received.selector;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/contracts/test/MockPool.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/IERC20.sol";
6 |
7 | contract MockPool {
8 |
9 | function withdraw(address token, uint amount) external {
10 | IERC20(token).transfer(msg.sender, amount);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/contracts/test/MockSplitter.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/ISplitter.sol";
6 | import "../interfaces/IERC20.sol";
7 | import "../interfaces/ITetuVaultV2.sol";
8 | import "../proxy/ControllableV3.sol";
9 |
10 | contract MockSplitter is ISplitter, ControllableV3 {
11 |
12 | address public override asset;
13 | address public override vault;
14 | uint public slippage;
15 | address[] public strategies;
16 | uint public constant HARDWORK_DELAY = 12 hours;
17 | mapping(address => bool) public pausedStrategies;
18 | mapping(address => uint) public lastHardWorks;
19 |
20 | function init(address controller_, address _asset, address _vault) external initializer override {
21 | __Controllable_init(controller_);
22 | asset = _asset;
23 | vault = _vault;
24 | }
25 |
26 | function coverPossibleStrategyLoss(uint /*earned*/, uint /*lost*/) external pure {
27 | // noop
28 | }
29 |
30 | function pauseInvesting(address strategy) external {
31 | require(!pausedStrategies[strategy], "SS: Paused");
32 | pausedStrategies[strategy] = true;
33 | }
34 |
35 | function continueInvesting(address strategy, uint /*apr*/) external {
36 | require(pausedStrategies[strategy], "SS: Not paused");
37 | pausedStrategies[strategy] = false;
38 | }
39 |
40 | function setSlippage(uint value) external {
41 | slippage = value;
42 | }
43 |
44 | function withdrawAllToVault() external override {
45 | withdrawToVault(IERC20(asset).balanceOf(address(this)));
46 | }
47 |
48 | function withdrawToVault(uint256 amount) public override {
49 | uint toSend = amount - amount * slippage / 1000;
50 | if (slippage != 0) {
51 | IERC20(asset).transfer(controller(), amount - toSend);
52 | }
53 | IERC20(asset).transfer(vault, toSend);
54 | }
55 |
56 | function doHardWork() external override {
57 | // noop
58 | }
59 |
60 | function investAll() external override {
61 | // noop
62 | }
63 |
64 | function totalAssets() external view override returns (uint256) {
65 | return IERC20(asset).balanceOf(address(this));
66 | }
67 |
68 | function isHardWorking() external pure override returns (bool) {
69 | return false;
70 | }
71 |
72 | function lost(uint amount) external {
73 | IERC20(asset).transfer(msg.sender, amount);
74 | }
75 |
76 | function coverLoss(uint amount) external {
77 | ITetuVaultV2(vault).coverLoss(amount);
78 | }
79 |
80 | /// @dev See {IERC165-supportsInterface}.
81 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
82 | return interfaceId == InterfaceIds.I_SPLITTER || super.supportsInterface(interfaceId);
83 | }
84 |
85 | function strategiesLength() external view returns (uint) {
86 | return strategies.length;
87 | }
88 |
89 | function rebalance(uint /*percent*/, uint /*lossTolerance*/) external pure override {}
90 | function getStrategyCapacity(address /*strategy*/) external pure override returns (uint) {return 0;}
91 | }
92 |
--------------------------------------------------------------------------------
/contracts/test/MockStakingToken.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../openzeppelin/ERC20Upgradeable.sol";
6 | import "../interfaces/IGauge.sol";
7 |
8 | contract MockStakingToken is ERC20Upgradeable {
9 |
10 | uint8 internal immutable _decimals;
11 | IGauge internal immutable gauge;
12 |
13 | constructor(
14 | string memory name_,
15 | string memory symbol_,
16 | uint8 decimals_,
17 | address gauge_
18 | ) {
19 | _decimals = decimals_;
20 | gauge = IGauge(gauge_);
21 | _init(name_, symbol_);
22 | }
23 |
24 | function _init(
25 | string memory name_,
26 | string memory symbol_
27 | ) internal initializer {
28 | __ERC20_init(name_, symbol_);
29 | }
30 |
31 | function decimals() public view override returns (uint8) {
32 | return _decimals;
33 | }
34 |
35 | function mint(address to, uint amount) external {
36 | _mint(to, amount);
37 | }
38 |
39 | function _afterTokenTransfer(
40 | address from,
41 | address to,
42 | uint
43 | ) internal override {
44 | gauge.handleBalanceChange(from);
45 | gauge.handleBalanceChange(to);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/contracts/test/MockStrategySimple.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 | import "../interfaces/IStrategyV2.sol";
7 | import "../interfaces/IERC20.sol";
8 |
9 | contract MockStrategySimple is ControllableV3, IStrategyV2 {
10 |
11 | string public constant override NAME = "mock strategy";
12 | string public override strategySpecificName = "mock strategy1";
13 | string public constant override PLATFORM = "test";
14 | string public constant override STRATEGY_VERSION = "1.0.0";
15 |
16 | address public override splitter;
17 | address public override asset;
18 | bool public override isReadyToHardWork;
19 | uint public override compoundRatio;
20 |
21 | uint internal slippage;
22 | uint internal lastEarned;
23 | uint internal lastLost;
24 |
25 | uint internal _capacity;
26 | address public override performanceReceiver;
27 | uint public override performanceFee;
28 |
29 | function init(
30 | address controller_,
31 | address _splitter,
32 | address _asset
33 | ) external initializer {
34 | __Controllable_init(controller_);
35 | splitter = _splitter;
36 | asset = _asset;
37 | isReadyToHardWork = true;
38 | _capacity = type(uint).max; // unlimited capacity by default
39 | performanceReceiver = IController(controller_).governance();
40 | performanceFee = 10_000;
41 | }
42 |
43 | function totalAssets() public view override returns (uint) {
44 | return IERC20(asset).balanceOf(address(this));
45 | }
46 |
47 | function withdrawAllToSplitter() external override returns (uint strategyLoss) {
48 | return withdrawToSplitter(totalAssets());
49 | }
50 |
51 | function withdrawToSplitter(uint amount) public override returns (uint strategyLoss) {
52 | uint _slippage = amount * slippage / 100;
53 | if (_slippage != 0) {
54 | IERC20(asset).transfer(controller(), _slippage);
55 | }
56 | IERC20(asset).transfer(splitter, amount - _slippage);
57 | return _slippage;
58 | }
59 |
60 | function investAll(
61 | uint amount_,
62 | bool updateTotalAssetsBeforeInvest_
63 | ) external pure override returns (
64 | uint strategyLoss
65 | ) {
66 | amount_; // hide warning
67 | updateTotalAssetsBeforeInvest_; // hide warning
68 | // noop
69 | return strategyLoss;
70 | }
71 |
72 | function doHardWork() external view override returns (uint earned, uint lost) {
73 | return (lastEarned, lastLost);
74 | }
75 |
76 | function setLast(uint earned, uint lost) external {
77 | lastEarned = earned;
78 | lastLost = lost;
79 | }
80 |
81 | function setSlippage(uint value) external {
82 | slippage = value;
83 | }
84 |
85 | function setCompoundRatio(uint value) external override {
86 | compoundRatio = value;
87 | }
88 |
89 | /// @notice Max amount that can be deposited to the strategy, see SCB-593
90 | function capacity() external view override returns (uint) {
91 | return _capacity;
92 | }
93 |
94 | function setCapacity(uint capacity_) external {
95 | _capacity = capacity_;
96 | }
97 |
98 | /// @notice Set performance fee and receiver
99 | function setupPerformanceFee(uint fee_, address receiver_) external {
100 | performanceFee = fee_;
101 | performanceReceiver = receiver_;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/contracts/test/MockStrategyStrict.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/IERC20.sol";
6 | import "../strategy/StrategyStrictBase.sol";
7 | import "./MockPool.sol";
8 |
9 | contract MockStrategyStrict is StrategyStrictBase {
10 |
11 | string public constant override NAME = "mock strategy strict";
12 | string public constant override PLATFORM = "test";
13 | string public constant override STRATEGY_VERSION = "1.0.0";
14 |
15 | bool public override isReadyToHardWork;
16 |
17 | uint internal slippage;
18 | uint internal slippageDeposit;
19 | uint internal lastEarned;
20 | uint internal lastLost;
21 |
22 | MockPool public pool;
23 |
24 | constructor() {
25 | isReadyToHardWork = true;
26 | pool = new MockPool();
27 | }
28 |
29 | function doHardWork() external view override returns (uint earned, uint lost) {
30 | return (lastEarned, lastLost);
31 | }
32 |
33 | /// @dev Amount of underlying assets invested to the pool.
34 | function investedAssets() public view override returns (uint) {
35 | return IERC20(asset).balanceOf(address(pool));
36 | }
37 |
38 | /// @dev Deposit given amount to the pool.
39 | function _depositToPool(uint amount) internal override {
40 | uint _slippage = amount * slippageDeposit / 100_000;
41 | if (_slippage != 0) {
42 | IERC20(asset).transfer(vault, _slippage);
43 | }
44 | if (amount - _slippage != 0) {
45 | IERC20(asset).transfer(address(pool), amount - _slippage);
46 | }
47 | }
48 |
49 | /// @dev Withdraw given amount from the pool.
50 | function _withdrawFromPool(uint amount) internal override returns (uint investedAssetsUSD, uint assetPrice) {
51 | assetPrice = 1e18;
52 | investedAssetsUSD = amount;
53 | pool.withdraw(asset, amount);
54 | uint _slippage = amount * slippage / 100_000;
55 | if (_slippage != 0) {
56 | IERC20(asset).transfer(vault, _slippage);
57 | }
58 | }
59 |
60 | /// @dev Withdraw all from the pool.
61 | function _withdrawAllFromPool() internal override returns (uint investedAssetsUSD, uint assetPrice) {
62 | assetPrice = 1e18;
63 | investedAssetsUSD = investedAssets();
64 | pool.withdraw(asset, investedAssets());
65 | uint _slippage = totalAssets() * slippage / 100_000;
66 | if (_slippage != 0) {
67 | IERC20(asset).transfer(vault, _slippage);
68 | }
69 | return (0, 0);
70 | }
71 |
72 | /// @dev If pool support emergency withdraw need to call it for emergencyExit()
73 | function _emergencyExitFromPool() internal override {
74 | pool.withdraw(asset, investedAssets());
75 | }
76 |
77 | /// @dev Claim all possible rewards.
78 | function _claim() internal override {
79 | // noop
80 | }
81 |
82 | function setSlippage(uint value) external {
83 | slippage = value;
84 | }
85 |
86 | function setSlippageDeposit(uint value) external {
87 | slippageDeposit = value;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/contracts/test/MockToken.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../openzeppelin/ERC20Upgradeable.sol";
6 |
7 | contract MockToken is ERC20Upgradeable {
8 |
9 | uint8 internal _decimals;
10 |
11 | constructor(
12 | string memory name_,
13 | string memory symbol_,
14 | uint8 decimals_
15 | ) {
16 | _init(name_, symbol_, decimals_);
17 | }
18 |
19 | function _init(
20 | string memory name_,
21 | string memory symbol_,
22 | uint8 decimals_
23 | ) internal initializer {
24 | __ERC20_init(name_, symbol_);
25 | _decimals = decimals_;
26 | }
27 |
28 | function decimals() public view override returns (uint8) {
29 | return _decimals;
30 | }
31 |
32 | function mint(address to, uint amount) external {
33 | _mint(to, amount);
34 | }
35 |
36 | function burn(address from, uint amount) external {
37 | _burn(from, amount);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/contracts/test/MockVaultSimple.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 | import "../vault/ERC4626Upgradeable.sol";
7 |
8 | contract MockVaultSimple is ERC4626Upgradeable, ControllableV3 {
9 | using SafeERC20 for IERC20;
10 |
11 | uint constant public FEE_DENOMINATOR = 100;
12 |
13 |
14 | function init(
15 | address controller_,
16 | IERC20 _asset,
17 | string memory _name,
18 | string memory _symbol
19 | ) external initializer {
20 | __ERC4626_init(_asset, _name, _symbol);
21 | __Controllable_init(controller_);
22 | }
23 |
24 | function totalAssets() public view override returns (uint) {
25 | return _asset.balanceOf(address(this));
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/contracts/test/MockVeDist.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 |
7 | contract MockVeDist {
8 |
9 | function checkpoint() external {
10 | // noop
11 | }
12 |
13 | function checkpointTotalSupply() external {
14 | // noop
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/contracts/test/MockVoter.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/IVeTetu.sol";
6 | import "../interfaces/IVoter.sol";
7 | import "../interfaces/IERC20.sol";
8 |
9 | contract MockVoter is IVoter {
10 |
11 | address public override ve;
12 | mapping(uint => uint) public mockVotes;
13 |
14 | constructor(address _ve) {
15 | ve = _ve;
16 | }
17 |
18 | function votedVaultsLength(uint veId) external view override returns (uint) {
19 | return mockVotes[veId];
20 | }
21 |
22 | function attachTokenToGauge(address, uint tokenId, address) external override {
23 | if (tokenId > 0) {
24 | IVeTetu(ve).attachToken(tokenId);
25 | }
26 | }
27 |
28 | function detachTokenFromGauge(address, uint tokenId, address) external override {
29 | if (tokenId > 0) {
30 | IVeTetu(ve).detachToken(tokenId);
31 | }
32 | }
33 |
34 | function distribute(address) external override {
35 | // noop
36 | }
37 |
38 | function distributeAll() external override {
39 | // noop
40 | }
41 |
42 | function voting(uint id) external {
43 | mockVotes[id]++;
44 | }
45 |
46 | function abstain(uint id) external {
47 | mockVotes[id]--;
48 | }
49 |
50 | function detachTokenFromAll(uint tokenId, address) external override {
51 | while (IVeTetu(ve).attachments(tokenId) > 0) {
52 | IVeTetu(ve).detachToken(tokenId);
53 | }
54 | mockVotes[tokenId] = 0;
55 | }
56 |
57 | function notifyRewardAmount(uint amount) external override {
58 | IERC20(IVeTetu(ve).tokens(0)).transferFrom(msg.sender, address(this), amount);
59 | }
60 |
61 | function isVotesExist(uint veId) external view override returns (bool) {
62 | return mockVotes[veId] > 0;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/contracts/test/Multicall.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | ////// /nix/store/im7ll7dx8gsw2da9k5xwbf8pbjfli2hc-multicall-df1e59d/src/Multicall.sol
6 | /* pragma solidity >=0.5.0; */
7 | /* pragma experimental ABIEncoderV2; */
8 |
9 | /// @title Multicall - Aggregate results from multiple read-only function calls
10 | /// @author Michael Elliot
11 | /// @author Joshua Levine
12 | /// @author Nick Johnson
13 | contract Multicall {
14 | struct Call {
15 | address target;
16 | bytes callData;
17 | }
18 |
19 | function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {
20 | blockNumber = block.number;
21 | returnData = new bytes[](calls.length);
22 | for (uint256 i = 0; i < calls.length; i++) {
23 | (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
24 | require(success);
25 | returnData[i] = ret;
26 | }
27 | }
28 |
29 | // Helper functions
30 | function getEthBalance(address addr) public view returns (uint256 balance) {
31 | balance = addr.balance;
32 | }
33 |
34 | function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
35 | blockHash = blockhash(blockNumber);
36 | }
37 |
38 | function getLastBlockHash() public view returns (bytes32 blockHash) {
39 | blockHash = blockhash(block.number - 1);
40 | }
41 |
42 | function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
43 | timestamp = block.timestamp;
44 | }
45 |
46 | function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
47 | difficulty = block.difficulty;
48 | }
49 |
50 | function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
51 | gaslimit = block.gaslimit;
52 | }
53 |
54 | function getCurrentBlockCoinbase() public view returns (address coinbase) {
55 | coinbase = block.coinbase;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/contracts/test/SlotsTest.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../proxy/ControllableV3.sol";
6 |
7 | contract SlotsTest is ControllableV3 {
8 | struct SomeStruct {
9 | uint a;
10 | uint b;
11 | }
12 |
13 | bytes32 internal constant _SLOT = bytes32(uint256(keccak256("slot")) - 1);
14 |
15 | mapping(uint => SomeStruct) public map;
16 |
17 | function initialize(address controller_) external initializer {
18 | __Controllable_init(controller_);
19 | }
20 |
21 | function setMapA(uint index, uint a) external {
22 | map[index].a = a;
23 | }
24 |
25 | function getBytes32() external view returns (bytes32 result) {
26 | return SlotsLib.getBytes32(_SLOT);
27 | }
28 |
29 | function getAddress() external view returns (address result) {
30 | return SlotsLib.getAddress(_SLOT);
31 | }
32 |
33 | function getUint() external view returns (uint result) {
34 | return SlotsLib.getUint(_SLOT);
35 | }
36 |
37 | function arrayLength() external view returns (uint result) {
38 | return SlotsLib.arrayLength(_SLOT);
39 | }
40 |
41 | function addressAt(uint index) external view returns (address result) {
42 | return SlotsLib.addressAt(_SLOT, index);
43 | }
44 |
45 | function uintAt(uint index) external view returns (uint result) {
46 | return SlotsLib.uintAt(_SLOT, index);
47 | }
48 |
49 | function setByte32(bytes32 value) external {
50 | SlotsLib.set(_SLOT, value);
51 | }
52 |
53 | function setAddress(address value) external {
54 | SlotsLib.set(_SLOT, value);
55 | }
56 |
57 | function setUint(uint value) external {
58 | SlotsLib.set(_SLOT, value);
59 | }
60 |
61 | function setAt(uint index, address value) external {
62 | SlotsLib.setAt(_SLOT, index, value);
63 | }
64 |
65 | function setAt(uint index, uint value) external {
66 | SlotsLib.setAt(_SLOT, index, value);
67 | }
68 |
69 | function setLength(uint length) external {
70 | SlotsLib.setLength(_SLOT, length);
71 | }
72 |
73 | function push(address value) external {
74 | SlotsLib.push(_SLOT, value);
75 | }
76 |
77 | }
78 |
79 |
80 | /// @dev extending SomeStruct with new member
81 | contract SlotsTest2 is ControllableV3 {
82 | struct SomeStruct {
83 | uint a;
84 | uint b;
85 | }
86 |
87 | mapping(uint => SomeStruct) public map;
88 |
89 | function initialize(address controller_) external initializer {
90 | __Controllable_init(controller_);
91 | }
92 |
93 | function setMapA(uint index, uint a) external {
94 | map[index].a = a;
95 | }
96 |
97 | function setMapB(uint index, uint b) external {
98 | map[index].b = b;
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/contracts/test/StakelessMultiPoolMock.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../reward/StakelessMultiPoolBase.sol";
6 |
7 | contract StakelessMultiPoolMock is StakelessMultiPoolBase {
8 |
9 | mapping(address => bool) public stakingTokens;
10 |
11 | function init(
12 | address controller_,
13 | address[] memory _stakingTokens,
14 | address _defaultRewardToken,
15 | uint duration_
16 | ) external initializer {
17 | __MultiPool_init(controller_, _defaultRewardToken, duration_);
18 | for (uint i; i < _stakingTokens.length; i++) {
19 | stakingTokens[_stakingTokens[i]] = true;
20 | }
21 | }
22 |
23 | // for test 2 deposits in one tx
24 | function testDoubleDeposit(address stakingToken, uint amount) external {
25 | uint amount0 = amount / 2;
26 | uint amount1 = amount - amount0;
27 | _registerBalanceIncreasing(stakingToken, msg.sender, amount0);
28 | _registerBalanceIncreasing(stakingToken, msg.sender, amount1);
29 | }
30 |
31 | // for test 2 withdraws in one tx
32 | function testDoubleWithdraw(address stakingToken, uint amount) external {
33 | uint amount0 = amount / 2;
34 | uint amount1 = amount - amount0;
35 | _registerBalanceDecreasing(stakingToken, msg.sender, amount0);
36 | _registerBalanceDecreasing(stakingToken, msg.sender, amount1);
37 | }
38 |
39 | function deposit(address stakingToken, uint amount) external {
40 | _registerBalanceIncreasing(stakingToken, msg.sender, amount);
41 | }
42 |
43 | function withdraw(address stakingToken, uint amount) external {
44 | _registerBalanceDecreasing(stakingToken, msg.sender, amount);
45 | }
46 |
47 | function getReward(address stakingToken, address account, address[] memory tokens) external {
48 | _getReward(stakingToken, account, tokens, account);
49 | }
50 |
51 | function notifyRewardAmount(address stakingToken, address token, uint amount) external {
52 | _notifyRewardAmount(stakingToken, token, amount, true);
53 | }
54 |
55 | function isStakeToken(address token) public view override returns (bool) {
56 | return stakingTokens[token];
57 | }
58 |
59 | /// @dev See {IERC165-supportsInterface}.
60 | function supportsInterface(bytes4 interfaceId) public view virtual override(StakelessMultiPoolBase) returns (bool) {
61 | return interfaceId == InterfaceIds.I_MULTI_POOL || super.supportsInterface(interfaceId);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/contracts/test/StrategyV2BaseEmpty.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity 0.8.17;
3 |
4 | import "../strategy/StrategyBaseV2.sol";
5 |
6 | contract StrategyV2BaseEmpty is StrategyBaseV2 {
7 | string public constant override NAME = "empty strategy";
8 | string public constant override PLATFORM = "test";
9 | string public constant override STRATEGY_VERSION = "1.0.0";
10 |
11 | function init() external {
12 | __StrategyBase_init(address(0), address(0));
13 | }
14 |
15 | function _claim() internal pure override returns (address[] memory rewardTokens, uint[] memory amounts) {}
16 |
17 | function _depositToPool(uint amount, bool /*updateTotalAssetsBeforeInvest_*/) internal override returns (uint strategyLoss) {}
18 |
19 | function _emergencyExitFromPool() internal virtual override {}
20 |
21 | function _withdrawAllFromPool() internal override returns (uint expectedWithdrewUSD, uint assetPrice, uint strategyLoss) {}
22 |
23 | function _withdrawFromPool(uint amount) internal override returns (uint expectedWithdrewUSD, uint assetPrice, uint strategyLoss) {}
24 |
25 | function capacity() external view returns (uint) {}
26 |
27 | function doHardWork() external returns (uint earned, uint lost) {}
28 |
29 | function isReadyToHardWork() external view returns (bool) {}
30 |
31 | function investedAssets() public view virtual override returns (uint) {}
32 | }
33 |
--------------------------------------------------------------------------------
/contracts/test/StrategyV3BaseEmpty.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity 0.8.17;
3 |
4 | import "../strategy/StrategyBaseV3.sol";
5 |
6 | contract StrategyV3BaseEmpty is StrategyBaseV3 {
7 | string public constant override NAME = "empty strategy";
8 | string public constant override PLATFORM = "test";
9 | string public constant override STRATEGY_VERSION = "1.0.0";
10 |
11 | function init() external {
12 | __StrategyBase_init(address(0), address(0));
13 | }
14 |
15 | function _claim() internal pure override returns (address[] memory rewardTokens, uint[] memory amounts) {}
16 |
17 | function _depositToPool(uint amount, bool /*updateTotalAssetsBeforeInvest_*/) internal override returns (uint strategyLoss) {}
18 |
19 | function _emergencyExitFromPool() internal virtual override {}
20 |
21 | function _withdrawAllFromPool() internal override returns (uint expectedWithdrewUSD, uint assetPrice, uint strategyLoss) {}
22 |
23 | function _withdrawFromPool(uint amount) internal override returns (uint expectedWithdrewUSD, uint assetPrice, uint strategyLoss) {}
24 |
25 | function capacity() external view returns (uint) {}
26 |
27 | function doHardWork() external returns (uint earned, uint lost) {}
28 |
29 | function isReadyToHardWork() external view returns (bool) {}
30 |
31 | function investedAssets() public view virtual override returns (uint) {}
32 | }
33 |
--------------------------------------------------------------------------------
/contracts/test/StringLibFacade.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity 0.8.17;
3 |
4 | import "../lib/StringLib.sol";
5 |
6 | contract StringLibFacade {
7 |
8 | function uintToString(uint value) external pure returns (string memory) {
9 | return StringLib.toString(value);
10 | }
11 |
12 | function toAsciiString(address x) external pure returns (string memory) {
13 | return StringLib.toAsciiString(x);
14 | }
15 |
16 | function char(bytes1 b) external pure returns (bytes1 c) {
17 | return StringLib.char(b);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/contracts/test/TetuERC165Test.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity 0.8.17;
3 |
4 | import "../tools/TetuERC165.sol";
5 |
6 | /// @author bogdoslav
7 | contract TetuERC165Test is TetuERC165 {
8 |
9 | // *************************************************************
10 | // EXTERNAL FUNCTIONS
11 | // *************************************************************
12 |
13 | function isInterfaceSupported(address contractAddress, bytes4 interfaceId) external view returns (bool) {
14 | return _isInterfaceSupported(contractAddress, interfaceId);
15 | }
16 |
17 | function requireInterface(address contractAddress, bytes4 interfaceId) external view {
18 | _requireInterface(contractAddress, interfaceId);
19 | }
20 |
21 | function isERC20(address contractAddress) external view returns (bool) {
22 | return _isERC20(contractAddress);
23 | }
24 |
25 | function requireERC20(address contractAddress) external view {
26 | _requireERC20(contractAddress);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/contracts/test/WrongNFTReceiver.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | contract WrongNFTReceiver {
6 |
7 | function onERC721Received(
8 | address,
9 | address,
10 | uint256,
11 | bytes calldata
12 | ) external pure returns (bytes4) {
13 | revert("stub revert");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/contracts/tools/BribeDistribution.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../interfaces/IERC20.sol";
6 | import "../interfaces/IVeDistributor.sol";
7 |
8 | contract BribeDistribution {
9 | //
10 | // string public constant VERSION = "1.0.0";
11 | //
12 | // address public owner;
13 | // address public pendingOwner;
14 | // address public operator;
15 | //
16 | // IVeDistributor public immutable veDist;
17 | // address public immutable token;
18 | // uint public round;
19 | //
20 | // constructor(address veDist_, address _token) {
21 | // veDist = IVeDistributor(veDist_);
22 | // token = _token;
23 | // owner = msg.sender;
24 | // }
25 | //
26 | // modifier onlyOwner() {
27 | // require(msg.sender == owner, "NOT_OWNER");
28 | // _;
29 | // }
30 | //
31 | // modifier onlyOperator() {
32 | // require(msg.sender == operator || msg.sender == owner, "NOT_OPERATOR");
33 | // _;
34 | // }
35 | //
36 | // function offerOwnership(address newOwner) external onlyOwner {
37 | // require(newOwner != address(0), "ZERO_ADDRESS");
38 | // pendingOwner = newOwner;
39 | // }
40 | //
41 | // function acceptOwnership() external {
42 | // require(msg.sender == pendingOwner, "NOT_OWNER");
43 | // owner = pendingOwner;
44 | // }
45 | //
46 | // function setOperator(address operator_) external onlyOwner {
47 | // operator = operator_;
48 | // }
49 | //
50 | // ////////////////// MAIN LOGIC //////////////////////
51 | //
52 | // function autoNotify() external onlyOperator {
53 | // _notify(IERC20(token).balanceOf(msg.sender), round % 2 == 0);
54 | // round++;
55 | // }
56 | //
57 | // function manualNotify(uint amount, bool fresh) external onlyOperator {
58 | // _notify(amount, fresh);
59 | // }
60 | //
61 | // function _notify(uint amount, bool fresh) internal {
62 | // if (amount != 0) {
63 | // IERC20(token).transferFrom(msg.sender, address(this), amount);
64 | // }
65 | //
66 | // uint toRewards = IERC20(token).balanceOf(address(this));
67 | // require(toRewards != 0, "ZERO_BALANCE");
68 | //
69 | // // assume we will have bribes once per 2 weeks. Need to use a half of the current balance in case of start of new 2 weeks epoch.
70 | // if (fresh) {
71 | // toRewards = toRewards / 2;
72 | // }
73 | //
74 | // IVeDistributor _veDist = veDist;
75 | //
76 | // IERC20(token).transfer(address(_veDist), toRewards);
77 | // _veDist.checkpoint();
78 | // _veDist.checkpointTotalSupply();
79 | // }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/contracts/tools/DepositHelperBaseChain.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./DepositHelperAbstract.sol";
6 |
7 | interface IRouter {
8 | function addLiquidity(
9 | address tokenA,
10 | address tokenB,
11 | bool stable,
12 | uint amountADesired,
13 | uint amountBDesired,
14 | uint amountAMin,
15 | uint amountBMin,
16 | address to,
17 | uint deadline
18 | ) external returns (uint amountA, uint amountB, uint liquidity);
19 | }
20 |
21 | contract DepositHelperBaseChain is DepositHelperAbstract {
22 | using SafeERC20 for IERC20;
23 |
24 | address public constant TETU_tUSDbC_AERODROME_LP = 0x924bb74AD42314E4434af5df984cca28b0529337;
25 | address public constant ASSET0 = 0x5E42c17CAEab64527D9d80d506a3FE01179afa02; // TETU
26 | address public constant ASSET1 = 0x68f0a05FDc8773d9a5Fd1304ca411ACc234ce22c; // tUSDbC
27 | IRouter public constant AERODROME_ROUTER = IRouter(0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43);
28 |
29 | constructor(address _oneInchRouter) DepositHelperAbstract(_oneInchRouter) {
30 | }
31 |
32 | function _convertToVeTetuLpUnderlying(
33 | bytes memory asset0SwapData,
34 | bytes memory asset1SwapData,
35 | address tokenIn,
36 | uint amountIn
37 | ) internal override returns (uint lpBalance, address pool){
38 | pool = TETU_tUSDbC_AERODROME_LP;
39 |
40 | IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
41 | _approveIfNeeds(tokenIn, amountIn, oneInchRouter);
42 |
43 | if (tokenIn != ASSET0) {
44 | (bool success,bytes memory result) = oneInchRouter.call(asset0SwapData);
45 | require(success, string(result));
46 | }
47 |
48 | if (tokenIn != ASSET1) {
49 | (bool success,bytes memory result) = oneInchRouter.call(asset1SwapData);
50 | require(success, string(result));
51 | }
52 |
53 | uint amount0 = IERC20(ASSET0).balanceOf(address(this));
54 | uint amount1 = IERC20(ASSET1).balanceOf(address(this));
55 |
56 | _approveIfNeeds(ASSET0, amount0, address(AERODROME_ROUTER));
57 | _approveIfNeeds(ASSET1, amount1, address(AERODROME_ROUTER));
58 |
59 | AERODROME_ROUTER.addLiquidity(
60 | ASSET0,
61 | ASSET1,
62 | false,
63 | amount0,
64 | amount1,
65 | 0,
66 | 0,
67 | address(this),
68 | block.timestamp
69 | );
70 |
71 | _sendRemainingToken(tokenIn);
72 | _sendRemainingToken(ASSET0);
73 | _sendRemainingToken(ASSET1);
74 |
75 |
76 | lpBalance = IERC20(pool).balanceOf(address(this));
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/contracts/tools/DepositHelperPolygon.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "./DepositHelperAbstract.sol";
6 |
7 |
8 | contract DepositHelperPolygon is DepositHelperAbstract {
9 | using SafeERC20 for IERC20;
10 |
11 | address public constant BALANCER_VAULT = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
12 | bytes32 public constant BALANCER_POOL_ID = 0xe2f706ef1f7240b803aae877c9c762644bb808d80002000000000000000008c2; // poolId of 80TETU-20USDC
13 | address public constant BALANCER_POOL_TOKEN = 0xE2f706EF1f7240b803AAe877C9C762644bb808d8; // 80TETU-20USDC
14 | address public constant ASSET0 = 0x255707B70BF90aa112006E1b07B9AeA6De021424; // TETU
15 | address public constant ASSET1 = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174; // USDC
16 |
17 | constructor(address _oneInchRouter) DepositHelperAbstract(_oneInchRouter) {
18 | }
19 |
20 | function _convertToVeTetuLpUnderlying(
21 | bytes memory asset0SwapData,
22 | bytes memory asset1SwapData,
23 | address tokenIn,
24 | uint amountIn
25 | ) internal override returns (uint bptBalance, address pool){
26 | address asset0 = ASSET0;
27 | address asset1 = ASSET1;
28 | IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
29 |
30 | _approveIfNeeds(tokenIn, amountIn, oneInchRouter);
31 | if (tokenIn != asset0) {
32 | (bool success,bytes memory result) = oneInchRouter.call(asset0SwapData);
33 | require(success, string(result));
34 | }
35 |
36 | if (tokenIn != asset1) {
37 | (bool success,bytes memory result) = oneInchRouter.call(asset1SwapData);
38 | require(success, string(result));
39 | }
40 |
41 | // add liquidity
42 | _joinBalancerPool(BALANCER_VAULT, BALANCER_POOL_ID, ASSET0, ASSET1, IERC20(ASSET0).balanceOf(address(this)), IERC20(ASSET1).balanceOf(address(this)));
43 |
44 | _sendRemainingToken(tokenIn);
45 | _sendRemainingToken(ASSET0);
46 | _sendRemainingToken(ASSET1);
47 |
48 | bptBalance = IERC20(BALANCER_POOL_TOKEN).balanceOf(address(this));
49 | pool = BALANCER_POOL_TOKEN;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/contracts/tools/ISolidlyPair.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | interface ISolidlyPair {
6 |
7 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
8 |
9 | function getReserves() external view returns (uint _reserve0, uint _reserve1, uint32 _blockTimestampLast);
10 |
11 | function getAmountOut(uint, address) external view returns (uint);
12 |
13 | function tokens() external view returns (address, address);
14 |
15 | function factory() external view returns (address);
16 |
17 | function stable() external view returns (bool);
18 | }
19 |
--------------------------------------------------------------------------------
/contracts/tools/PerfFeeTreasury.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../openzeppelin/SafeERC20.sol";
6 |
7 | contract PerfFeeTreasury {
8 | using SafeERC20 for IERC20;
9 |
10 | address public governance;
11 | address public pendingGovernance;
12 |
13 | constructor(address _governance) {
14 | governance = _governance;
15 | }
16 |
17 | modifier onlyGovernance() {
18 | require(msg.sender == governance, "NOT_GOV");
19 | _;
20 | }
21 |
22 | function offerOwnership(address newOwner) external onlyGovernance {
23 | require(newOwner != address(0), "ZERO_ADDRESS");
24 | pendingGovernance = newOwner;
25 | }
26 |
27 | function acceptOwnership() external {
28 | require(msg.sender == pendingGovernance, "NOT_GOV");
29 | governance = pendingGovernance;
30 | }
31 |
32 | function claim(address[] memory tokens) external onlyGovernance {
33 | address _governance = governance;
34 | for (uint i = 0; i < tokens.length; ++i) {
35 | IERC20(tokens[i]).safeTransfer(_governance, IERC20(tokens[i]).balanceOf(address(this)));
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/contracts/tools/RewardsRedirector.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../openzeppelin/SafeERC20.sol";
6 | import "../interfaces/IGauge.sol";
7 | import "../openzeppelin/EnumerableSet.sol";
8 |
9 | contract RewardsRedirector {
10 | using SafeERC20 for IERC20;
11 | using EnumerableSet for EnumerableSet.AddressSet;
12 |
13 | string public constant VERSION = "1.0.0";
14 |
15 | address public owner;
16 | address public pendingOwner;
17 | address public gauge;
18 | EnumerableSet.AddressSet internal operators;
19 | EnumerableSet.AddressSet internal redirected;
20 | mapping(address => address[]) public redirectedVaults;
21 |
22 | constructor(address _owner, address _gauge) {
23 | owner = _owner;
24 | gauge = _gauge;
25 | operators.add(_owner);
26 | }
27 |
28 | modifier onlyOwner() {
29 | require(msg.sender == owner, "!owner");
30 | _;
31 | }
32 |
33 | modifier onlyOperator() {
34 | require(operators.contains(msg.sender), "!operator");
35 | _;
36 | }
37 |
38 | /////////////////// VIEWS ////////////////////
39 |
40 | function getOperators() external view returns (address[] memory) {
41 | return operators.values();
42 | }
43 |
44 | function getRedirected() external view returns (address[] memory) {
45 | return redirected.values();
46 | }
47 |
48 | function getRedirectedVaults(address adr) external view returns (address[] memory) {
49 | return redirectedVaults[adr];
50 | }
51 |
52 | /////////////////// GOV ////////////////////
53 |
54 | function offerOwnership(address newOwner) external onlyOwner {
55 | require(newOwner != address(0), "zero");
56 | pendingOwner = newOwner;
57 | }
58 |
59 | function acceptOwnership() external {
60 | require(msg.sender == pendingOwner, "!owner");
61 | owner = pendingOwner;
62 | }
63 |
64 | function changeOperator(address adr, bool status) external onlyOwner {
65 | if (status) {
66 | operators.add(adr);
67 | } else {
68 | operators.remove(adr);
69 | }
70 | }
71 |
72 | function changeRedirected(address adr, address[] calldata vaults, bool status) external onlyOwner {
73 | if (status) {
74 | redirected.add(adr);
75 | redirectedVaults[adr] = vaults;
76 | } else {
77 | redirected.remove(adr);
78 | delete redirectedVaults[adr];
79 | }
80 | }
81 |
82 | /////////////////// MAIN LOGIC ////////////////////
83 |
84 | function claimRewards() external onlyOperator {
85 | address _gauge = gauge;
86 | address[] memory _redirected = redirected.values();
87 | for (uint j; j < _redirected.length; ++j) {
88 | address[] memory _vaults = redirectedVaults[_redirected[j]];
89 | for (uint i; i < _vaults.length; ++i) {
90 | IGauge(_gauge).getAllRewards(_vaults[i], _redirected[j]);
91 | }
92 | }
93 | }
94 |
95 | function withdraw(address token) external onlyOperator {
96 | IERC20(token).safeTransfer(msg.sender, IERC20(token).balanceOf(address(this)));
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/contracts/tools/TetuERC165.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 | pragma solidity 0.8.17;
3 |
4 | import "../openzeppelin/ERC165.sol";
5 | import "../interfaces/IERC20.sol";
6 | import "../lib/InterfaceIds.sol";
7 |
8 | /// @dev Tetu Implementation of the {IERC165} interface extended with helper functions.
9 | /// @author bogdoslav
10 | abstract contract TetuERC165 is ERC165 {
11 |
12 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
13 | return interfaceId == InterfaceIds.I_TETU_ERC165 || super.supportsInterface(interfaceId);
14 | }
15 |
16 | // *************************************************************
17 | // HELPER FUNCTIONS
18 | // *************************************************************
19 | /// @author bogdoslav
20 |
21 | /// @dev Checks what interface with id is supported by contract.
22 | /// @return bool. Do not throws
23 | function _isInterfaceSupported(address contractAddress, bytes4 interfaceId) internal view returns (bool) {
24 | require(contractAddress != address(0), "Zero address");
25 | // check what address is contract
26 | uint codeSize;
27 | assembly {
28 | codeSize := extcodesize(contractAddress)
29 | }
30 | if (codeSize == 0) return false;
31 |
32 | try IERC165(contractAddress).supportsInterface(interfaceId) returns (bool isSupported) {
33 | return isSupported;
34 | } catch {
35 | }
36 | return false;
37 | }
38 |
39 | /// @dev Checks what interface with id is supported by contract and reverts otherwise
40 | function _requireInterface(address contractAddress, bytes4 interfaceId) internal view {
41 | require(_isInterfaceSupported(contractAddress, interfaceId), "Interface is not supported");
42 | }
43 |
44 | /// @dev Checks what address is ERC20.
45 | /// @return bool. Do not throws
46 | function _isERC20(address contractAddress) internal view returns (bool) {
47 | require(contractAddress != address(0), "Zero address");
48 | // check what address is contract
49 | uint codeSize;
50 | assembly {
51 | codeSize := extcodesize(contractAddress)
52 | }
53 | if (codeSize == 0) return false;
54 |
55 | bool totalSupplySupported;
56 | try IERC20(contractAddress).totalSupply() returns (uint) {
57 | totalSupplySupported = true;
58 | } catch {
59 | }
60 |
61 | bool balanceSupported;
62 | try IERC20(contractAddress).balanceOf(address(this)) returns (uint) {
63 | balanceSupported = true;
64 | } catch {
65 | }
66 |
67 | return totalSupplySupported && balanceSupported;
68 | }
69 |
70 |
71 | /// @dev Checks what interface with id is supported by contract and reverts otherwise
72 | function _requireERC20(address contractAddress) internal view {
73 | require(_isERC20(contractAddress), "Not ERC20");
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/contracts/vault/VaultInsurance.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BUSL-1.1
2 |
3 | pragma solidity 0.8.17;
4 |
5 | import "../openzeppelin/SafeERC20.sol";
6 | import "../tools/TetuERC165.sol";
7 | import "../interfaces/IERC20.sol";
8 | import "../interfaces/IVaultInsurance.sol";
9 | import "../interfaces/ITetuVaultV2.sol";
10 | import "../lib/InterfaceIds.sol";
11 |
12 | /// @title Simple dedicated contract for store vault fees
13 | /// @author belbix
14 | contract VaultInsurance is TetuERC165, IVaultInsurance {
15 | using SafeERC20 for IERC20;
16 |
17 | /// @dev Vault address
18 | address public override vault;
19 | /// @dev Vault underlying asset
20 | address public override asset;
21 |
22 | /// @dev Init contract with given attributes.
23 | /// Should be called from factory during creation process.
24 | function init(address _vault, address _asset) external override {
25 | require(vault == address(0) && asset == address(0), "INITED");
26 | _requireInterface(_vault, InterfaceIds.I_TETU_VAULT_V2);
27 | _requireERC20(_asset);
28 |
29 | vault = _vault;
30 | asset = _asset;
31 | }
32 |
33 | /// @dev Transfer tokens to vault in case of covering need.
34 | function transferToVault(uint amount) external override {
35 | require(msg.sender == vault, "!VAULT");
36 | IERC20(asset).safeTransfer(msg.sender, amount);
37 | }
38 |
39 | /// @dev See {IERC165-supportsInterface}.
40 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
41 | return interfaceId == InterfaceIds.I_VAULT_INSURANCE || super.supportsInterface(interfaceId);
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/log_settings.ts:
--------------------------------------------------------------------------------
1 | import {ISettingsParam} from "tslog";
2 |
3 | // tslint:disable-next-line:ban-ts-ignore
4 | // @ts-ignore
5 | const logSettings: ISettingsParam = {
6 | colorizePrettyLogs: false,
7 | dateTimeTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
8 | displayLogLevel: false,
9 | displayLoggerName: false,
10 | displayFunctionName: false,
11 | displayFilePath: 'hidden',
12 | }
13 |
14 | export default (logSettings);
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@tetu_io/tetu-contracts-v2",
3 | "version": "2.1.6",
4 | "description": "TETU solidity base contracts V2",
5 | "main": "dist/index.js",
6 | "types": "dist/index.d.ts",
7 | "directories": {
8 | "contracts": "contracts",
9 | "dist": "dist"
10 | },
11 | "scripts": {
12 | "build-module": "npm run build && tsc",
13 | "prepare": "npm run build-module",
14 | "build": "npm run clean && npm run compile",
15 | "clean": "npx hardhat clean",
16 | "compile": "npx hardhat compile",
17 | "test": "npm run build && npx hardhat test",
18 | "coverage": "npm run build && npx cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" hardhat coverage --temp artifacts --max-memory 4096",
19 | "slither": "npm run build && slither .",
20 | "lint": "tslint -p tsconfig.json",
21 | "lint-fix": "tslint --fix -p tsconfig.json",
22 | "publish-npm": "npm publish --access public",
23 | "up": "hardhat run scripts/gov/execute-upgrades.ts --network matic"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "https://github.com/tetu-io/tetu-contracts-v2.git"
28 | },
29 | "author": "TETU team ",
30 | "license": "MIT",
31 | "homepage": "https://tetu.io",
32 | "dependencies": {
33 | "@nomiclabs/hardhat-ethers": "^2.2.1",
34 | "@nomiclabs/hardhat-etherscan": "^3.1.3",
35 | "@nomiclabs/hardhat-solhint": "^2.0.1",
36 | "@nomiclabs/hardhat-waffle": "^2.0.3",
37 | "@nomiclabs/hardhat-web3": "^2.0.0",
38 | "@typechain/ethers-v5": "^10.2.0",
39 | "@typechain/hardhat": "^6.1.5",
40 | "@types/chai": "^4.3.4",
41 | "@types/chai-as-promised": "^7.1.5",
42 | "@types/chai-string": "^1.4.2",
43 | "@types/mocha": "^10.0.1",
44 | "@types/node": "^18.11.14",
45 | "axios": "^1.2.1",
46 | "chai": "^4.3.7",
47 | "chai-as-promised": "^7.1.1",
48 | "dotenv": "^16.0.3",
49 | "ethereum-waffle": "^3.4.4",
50 | "ethereumjs-tx": "^2.1.2",
51 | "ethers": "^5.7.2",
52 | "graphql": "^16.6.0",
53 | "graphql-request": "^5.1.0",
54 | "hardhat": "2.14.1",
55 | "hardhat-abi-exporter": "^2.10.1",
56 | "hardhat-contract-sizer": "^2.6.1",
57 | "hardhat-deploy": "^0.11.22",
58 | "hardhat-gas-reporter": "^1.0.9",
59 | "mocha": "^10.2.0",
60 | "solidity-coverage": "^0.8.2",
61 | "ts-generator": "^0.1.1",
62 | "ts-node": "^10.9.1",
63 | "tslint": "^6.1.3",
64 | "tslog": "^4.4.4",
65 | "typechain": "^8.1.1",
66 | "typescript": "^4.9.4",
67 | "yargs": "^17.6.2"
68 | },
69 | "engines": {
70 | "node": "18.x.x"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/scripts/addresses/addresses.ts:
--------------------------------------------------------------------------------
1 | import {CoreAddresses} from "../models/CoreAddresses";
2 | import {GoerliAddresses} from "./goerli";
3 | import {PolygonAddresses} from "./polygon";
4 | import {SepoliaAddresses} from "./sepolia";
5 | import {ToolsAddresses} from "../models/ToolsAddresses";
6 | import {BaseAddresses} from "./base";
7 | import {ZkEvmAddresses} from "./zkevm";
8 |
9 | // tslint:disable-next-line:no-var-requires
10 | const hre = require("hardhat");
11 |
12 | export class Addresses {
13 |
14 | public static CORE = new Map([
15 | [5, GoerliAddresses.CORE_ADDRESSES],
16 | [11155111, SepoliaAddresses.CORE_ADDRESSES],
17 | [137, PolygonAddresses.CORE_ADDRESSES],
18 | [8453, BaseAddresses.CORE_ADDRESSES],
19 | [1101, ZkEvmAddresses.CORE_ADDRESSES],
20 | ]);
21 |
22 | public static TOOLS = new Map([
23 | [137, PolygonAddresses.TOOLS_ADDRESSES],
24 | [8453, BaseAddresses.TOOLS_ADDRESSES],
25 | [1101, ZkEvmAddresses.TOOLS_ADDRESSES],
26 | ]);
27 |
28 | public static getCore(): CoreAddresses {
29 | return Addresses.CORE.get(hre.network.config.chainId) as CoreAddresses;
30 | }
31 |
32 | public static getTools(): ToolsAddresses {
33 | return Addresses.TOOLS.get(hre.network.config.chainId) as ToolsAddresses;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/scripts/addresses/base.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:variable-name */
2 | // noinspection JSUnusedGlobalSymbols
3 |
4 | import {CoreAddresses} from "../models/CoreAddresses";
5 | import {ToolsAddresses} from "../models/ToolsAddresses";
6 |
7 | // noinspection SpellCheckingInspection
8 | export class BaseAddresses {
9 |
10 | public static CORE_ADDRESSES = new CoreAddresses(
11 | "0x5E42c17CAEab64527D9d80d506a3FE01179afa02", // tetu
12 | "0x255707B70BF90aa112006E1b07B9AeA6De021424", // controller
13 | "0xb8bA82F19A9Be6CbF6DAF9BF4FBCC5bDfCF8bEe6", // ve
14 | "0xA2c5911b6EcB4Da440C93F8b7dAa90c68F53E26a", // veDist old 0x875976AeF383Fe4135B93C3989671056c4dEcDFF
15 | "0xD8a4054d63fCb0030BC73E2323344Ae59A19E92b", // gauge
16 | "0x0B62ad43837A69Ad60289EEea7C6e907e759F6E8", // bribe
17 | "0xFC9b894D0b4a34AB41278Df5F2aBEEb5de95c9e4", // tetuVoter
18 | "0xCa9C8Fba773caafe19E6140eC0A7a54d996030Da", // platformVoter
19 | "0xdfB765935D7f4e38641457c431F89d20Db571674", // forwarder
20 | "0xdc08482Fe34ccf74300e996966030cAc0F81F271", // vaultFactory
21 | "0x27af55366a339393865FC5943C04bc2600F55C9F", // investFundV2
22 | );
23 |
24 | public static TOOLS_ADDRESSES = new ToolsAddresses(
25 | "0x22e2625F9d8c28CB4BcE944E9d64efb4388ea991",
26 | "0x51002Cad5e6FbE3856311f431E1c41c46Acc5D47",
27 | "0x1Ae75D0A2AFE092b1aC417c5c43515E54eE12E51",
28 | );
29 |
30 | public static GOVERNANCE = "0x3f5075195b96B60d7D26b5cDe93b64A6D9bF33e2".toLowerCase();
31 |
32 | // Additional TETU contracts
33 | public static HARDWORK_RESOLVER = "".toLowerCase();
34 | public static FORWARDER_RESOLVER = "".toLowerCase();
35 | public static SPLITTER_REBALANCE_RESOLVER = "".toLowerCase();
36 | public static PERF_FEE_TREASURY = "0xc4B7b554af7a82595e7e6Fab932562d5d2e273b4".toLowerCase();
37 | public static TETU_BRIDGED_PROCESSING = "".toLowerCase();
38 | public static REWARDS_REDIRECTOR = "0x57577b27814f4166E2340580C49c9726549677e0".toLowerCase();
39 | public static BRIBE_DISTRIBUTION = "".toLowerCase();
40 | public static DEPOSIT_HELPER_V2 = "0x6efecCc5112c778bD3bA6ce496Cc6816aBbE187C".toLowerCase();
41 | public static ONE_INCH_ROUTER_V5 = "0x1111111254EEB25477B68fb85Ed929f73A960582".toLowerCase();
42 |
43 | // Tetu V2 vaults and strategies
44 |
45 | public static tUSDbC = "0x68f0a05FDc8773d9a5Fd1304ca411ACc234ce22c".toLowerCase();
46 |
47 |
48 | // tokens
49 | public static TETU_TOKEN = "0x5E42c17CAEab64527D9d80d506a3FE01179afa02".toLowerCase();
50 | public static TETU_tUSDbC_AERODROME_LP = "0x924bb74AD42314E4434af5df984cca28b0529337".toLowerCase();
51 | public static USDbC_tUSDbC_AERODROME_LP = "0x07Eca3F678C86B89e428F452B9d5bbcb38B749Cd".toLowerCase();
52 | public static USDbC_tUSDbC_UNI3_POOL = "0x99a17985111FcB2B0544b0A19d4585ab671681C9".toLowerCase();
53 |
54 | public static WETH_TOKEN = '0x4200000000000000000000000000000000000006'.toLowerCase();
55 |
56 | public static USDC_TOKEN = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'.toLowerCase();
57 | public static USDbC_TOKEN = '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'.toLowerCase();
58 | public static axlUSDC_TOKEN = '0xEB466342C4d449BC9f53A865D5Cb90586f405215'.toLowerCase();
59 | public static crvUSD_TOKEN = '0x417Ac0e078398C154EdFadD9Ef675d30Be60Af93'.toLowerCase();
60 | public static USDT_TOKEN = ''.toLowerCase();
61 |
62 | public static WBTC_TOKEN = ''.toLowerCase();
63 | public static DAI_TOKEN = ''.toLowerCase();
64 | public static CRV_TOKEN = '0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415'.toLowerCase();
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/scripts/addresses/goerli.ts:
--------------------------------------------------------------------------------
1 | import {CoreAddresses} from "../models/CoreAddresses";
2 |
3 | export class GoerliAddresses {
4 |
5 | public static CORE_ADDRESSES = new CoreAddresses(
6 | "0x88a12B7b6525c0B46c0c200405f49cE0E72D71Aa", // tetu
7 | "0x0EFc2D2D054383462F2cD72eA2526Ef7687E1016", // controller
8 | "0xA43eA51b3251f96bB48c48567A93b15e7e4b99F6", // ve
9 | "0x6B2e0fACD2F2A8f407aC591067Ac06b5d29247E4", // veDist
10 | "0x7AD5935EA295c4E743e4f2f5B4CDA951f41223c2", // gauge
11 | "0x81367059892aa1D8503a79a0Af9254DD0a09afBF", // bribe
12 | "0x225084D30cc297F3b177d9f93f5C3Ab8fb6a1454", // tetuVoter
13 | "0x422282F18CFE573e7dc6BEcC7242ffad43340aF8", // platformVoter
14 | "0xeFBc16b8c973DecA383aAAbAB07153D2EB676556", // forwarder
15 | "0xCF66857b468740d6dbF9cE11929A9c03DDA12988", // vaultFactory
16 | "", // investFundV2
17 | );
18 |
19 | }
20 |
21 |
22 | // usdc: 0x308A756B4f9aa3148CaD7ccf8e72c18C758b2EF2
23 | // btc: 0x27af55366a339393865FC5943C04bc2600F55C9F
24 | // weth: 0xbf1e638871c59859db851674c7f94efcb0f40954
25 | // liquidator: 0x3bDbd2Ed1A214Ca4ba4421ddD7236ccA3EF088b6
26 | // factory: 0xB6Ca119F30B3E7F6589F8a053c2a10B753846e78
27 | // uniSwapper: 0xF9E426dF37D75875b136d9D25CB9f27Ee9E43C4f
28 | // usdcBtc: 0x53cBAb0D7E5e2B44216B1AB597D85E33C23Fe1Db
29 | // usdcWeth: 0x9B09fc5Efb7a16b15F53130f06AE21f1fC106680
30 | // btcWeth: 0x01490bd35C56766dD20D2b347EF73b6E40562779
31 | // usdcTetu: 0x58639D7ab0E26373205B9f54585c719a3F652650
32 |
--------------------------------------------------------------------------------
/scripts/addresses/sepolia.ts:
--------------------------------------------------------------------------------
1 | import {CoreAddresses} from "../models/CoreAddresses";
2 |
3 | export class SepoliaAddresses {
4 |
5 | public static CORE_ADDRESSES = new CoreAddresses(
6 | "0x549aE613Bb492CCf68A6620848C80262709a1fb4", // tetu
7 | "0xbf1fc29668e5f5Eaa819948599c9Ac1B1E03E75F", // controller
8 | "0x286c02C93f3CF48BB759A93756779A1C78bCF833", // ve
9 | "0x0A0846c978a56D6ea9D2602eeb8f977B21F3207F", // veDist
10 | "0x00379dD90b2A337C4652E286e4FBceadef940a21", // gauge
11 | "0x57Cf87b92E38f619bBeB2F13800730e668d69d7D", // bribe
12 | "0xB5A5D5fE893bC26C6E70CEbb8a193f764A438fd5", // tetuVoter
13 | "0x13d862a01d0AB241509A2e47e31d0db04e9b9F49", // platformVoter
14 | "0xbEB411eAD71713E7f2814326498Ff2a054242206", // forwarder
15 | "0xFC9b894D0b4a34AB41278Df5F2aBEEb5de95c9e4", // vaultFactory
16 | "", // investFundV2
17 | );
18 |
19 | }
20 |
21 | // deposit helper 0x6d85966b5280Bfbb479E0EBA00Ac5ceDfe8760D3
22 |
23 | // usdc: 0x27af55366a339393865FC5943C04bc2600F55C9F
24 | // btc: 0x0ed08c9A2EFa93C4bF3C8878e61D2B6ceD89E9d7
25 | // weth: 0x078b7c9304eBA754e916016E8A8939527076f991
26 | // liquidator: 0x8d6479dF2c152F99C23493c8ebbaf63DC586024b
27 | // factory: 0xB393cA1442621c3356600e5B10B3510B5180d948
28 | // uniSwapper: 0x01D0b17AC7B72cD4b051840e27A2134F25C53265
29 | // usdcBtc: 0xB4747653510E8a4DE0A03E2bAb09Dd5150DAad34
30 | // usdcWeth: 0xf210A6B37ddf47517c5d9E5AE3d24Bea5E398fa8
31 | // btcWeth: 0x55BC8E9C917CEB8D9195198c5F4972C2E443280A
32 | // usdcTetu: 0x27AaD9E67Ad9596D6f3f23c71D4cB5ef2080CE2F
33 |
--------------------------------------------------------------------------------
/scripts/addresses/zkevm.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:variable-name */
2 | // noinspection JSUnusedGlobalSymbols
3 |
4 | import {CoreAddresses} from "../models/CoreAddresses";
5 | import {ToolsAddresses} from "../models/ToolsAddresses";
6 |
7 | // noinspection SpellCheckingInspection
8 | export class ZkEvmAddresses {
9 |
10 | public static CORE_ADDRESSES = new CoreAddresses(
11 | "0x7C1B24c139a3EdA18Ab77C8Fa04A0F816C23e6D4", // tetu
12 | "0x35B0329118790B8c8FC36262812D92a4923C6795", // controller
13 | "0x0000000000000000000000000000000000000000", // ve
14 | "0x0000000000000000000000000000000000000000", // veDist
15 | "0xd353254872E8797B159594c1E528b8Be9a6cb1F8", // gauge
16 | "0x0000000000000000000000000000000000000000", // bribe
17 | "0x099C314F792e1F91f53765Fc64AaDCcf4dCf1538", // tetuVoter
18 | "0x0000000000000000000000000000000000000000", // platformVoter
19 | "0x255707B70BF90aa112006E1b07B9AeA6De021424", // forwarder
20 | "0xeFBc16b8c973DecA383aAAbAB07153D2EB676556", // vaultFactory
21 | "0x5373C3d09C39D8F256f88E08aa61402FE14A3792", // investFundV2
22 | );
23 |
24 | public static TOOLS_ADDRESSES = new ToolsAddresses(
25 | "0xBcda73B7184D5974F77721db79ff8BA190b342ce",
26 | "0x60E684643d546b657bfeE9c01Cb40E62EC1fe1e2",
27 | "0x914F48367E54033Be83d939ed20e6611e23DDB99",
28 | );
29 |
30 | public static GOVERNANCE = "".toLowerCase(); // todo
31 |
32 | // Additional TETU contracts
33 | public static HARDWORK_RESOLVER = "".toLowerCase();
34 | public static FORWARDER_RESOLVER = "".toLowerCase();
35 | public static SPLITTER_REBALANCE_RESOLVER = "".toLowerCase();
36 | public static PERF_FEE_TREASURY = "".toLowerCase(); // todo
37 | public static TETU_BRIDGED_PROCESSING = "".toLowerCase();
38 | public static REWARDS_REDIRECTOR = "".toLowerCase(); // todo
39 | public static BRIBE_DISTRIBUTION = "".toLowerCase();
40 | public static DEPOSIT_HELPER_V2 = "".toLowerCase(); // todo
41 |
42 | public static ONE_INCH_ROUTER_V5 = "TODO:0x1111111254EEB25477B68fb85Ed929f73A960582".toLowerCase(); // todo there is no 1inch on zkEvm
43 | public static OPENOCEAN_ROUTER = "0x6dd434082EAB5Cd134B33719ec1FF05fE985B97b".toLowerCase();
44 |
45 | // Tetu V2 vaults and strategies
46 |
47 | public static tUSDC = "0x3650823873F34a019533db164f492e09365cfa7E".toLowerCase();
48 |
49 |
50 | // tokens
51 | public static TETU_TOKEN = "0x7C1B24c139a3EdA18Ab77C8Fa04A0F816C23e6D4".toLowerCase();
52 |
53 | public static WETH_TOKEN = '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9'.toLowerCase();
54 |
55 | public static USDC_TOKEN = '0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035'.toLowerCase();
56 | public static USDT_TOKEN = '0x1E4a5963aBFD975d8c9021ce480b42188849D41d'.toLowerCase();
57 |
58 | public static WBTC_TOKEN = '0xEA034fb02eB1808C2cc3adbC15f447B93CbE08e1'.toLowerCase();
59 | public static DAI_TOKEN = '0xC5015b9d9161Dca7e18e32f6f25C4aD850731Fd4'.toLowerCase();
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployAllProdSimplified.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {InvestFundV2__factory} from "../../typechain";
4 | import {RunHelper} from "../utils/RunHelper";
5 | import {Addresses} from "../addresses/addresses";
6 | import {Misc} from "../utils/Misc";
7 |
8 | async function main() {
9 | const signer = (await ethers.getSigners())[0];
10 | const core = Addresses.getCore();
11 | const tools = Addresses.getTools();
12 |
13 | const tetu = core.tetu;
14 | const controller = await DeployerUtils.deployController(signer);
15 | const gauge = await DeployerUtils.deployMultiGaugeNoBoost(signer, controller.address, tetu);
16 | const tetuVoter = await DeployerUtils.deployTetuVoterSimplified(signer, controller.address, tetu, gauge.address);
17 | const forwarder = await DeployerUtils.deployForwarderSimplified(signer, controller.address, tetu);
18 | const fundAdr = await DeployerUtils.deployProxy(signer, 'InvestFundV2');
19 | const investFund = InvestFundV2__factory.connect(fundAdr, signer);
20 | await RunHelper.runAndWait2(investFund.populateTransaction.init(controller.address));
21 |
22 | const vaultImpl = await DeployerUtils.deployContract(signer, 'TetuVaultV2');
23 | const vaultInsuranceImpl = await DeployerUtils.deployContract(signer, 'VaultInsurance');
24 | const splitterImpl = await DeployerUtils.deployContract(signer, 'StrategySplitterV2');
25 |
26 | const vaultFactory = await DeployerUtils.deployVaultFactory(
27 | signer,
28 | controller.address,
29 | vaultImpl.address,
30 | vaultInsuranceImpl.address,
31 | splitterImpl.address,
32 | );
33 |
34 | await RunHelper.runAndWait2(controller.populateTransaction.announceAddressChange(2, tetuVoter.address));
35 | await RunHelper.runAndWait2(controller.populateTransaction.announceAddressChange(4, tools.liquidator));
36 | await RunHelper.runAndWait2(controller.populateTransaction.announceAddressChange(5, forwarder.address));
37 | await RunHelper.runAndWait2(controller.populateTransaction.announceAddressChange(6, fundAdr));
38 |
39 |
40 | await RunHelper.runAndWait2(controller.populateTransaction.changeAddress(2)); // TETU_VOTER
41 | await RunHelper.runAndWait2(controller.populateTransaction.changeAddress(4)); // LIQUIDATOR
42 | await RunHelper.runAndWait2(controller.populateTransaction.changeAddress(5)); // FORWARDER
43 | await RunHelper.runAndWait2(controller.populateTransaction.changeAddress(6)); // INVEST_FUND
44 |
45 | const result = ` public static CORE_ADDRESSES = new CoreAddresses(
46 | "${tetu}", // tetu
47 | "${controller.address}", // controller
48 | "${Misc.ZERO_ADDRESS}", // ve
49 | "${Misc.ZERO_ADDRESS}", // veDist
50 | "${gauge.address}", // gauge
51 | "${Misc.ZERO_ADDRESS}", // bribe
52 | "${tetuVoter.address}", // tetuVoter
53 | "${Misc.ZERO_ADDRESS}", // platformVoter
54 | "${forwarder.address}", // forwarder
55 | "${vaultFactory.address}", // vaultFactory
56 | "${investFund.address}", // investFund
57 | );`
58 |
59 | DeployerUtils.createFolderAndWriteFileSync('tmp/deployed/core.txt', result);
60 | }
61 |
62 | main()
63 | .then(() => {
64 | console.log('Script finished successfully');
65 | process.exit(0);
66 | })
67 | .catch(error => {
68 | console.error(error);
69 | process.exit(1);
70 | });
71 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployAllTestnet.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {writeFileSync} from "fs";
4 | import {InvestFundV2__factory} from "../../typechain";
5 | import {RunHelper} from "../utils/RunHelper";
6 |
7 | async function main() {
8 | const signer = (await ethers.getSigners())[0];
9 |
10 | const tetu = await DeployerUtils.deployMockToken(signer, 'TETU');
11 | const controller = await DeployerUtils.deployController(signer);
12 | const ve = await DeployerUtils.deployVeTetu(signer, tetu.address, controller.address);
13 | const gauge = await DeployerUtils.deployMultiGauge(signer, controller.address, ve.address, tetu.address);
14 | const bribe = await DeployerUtils.deployMultiBribe(signer, controller.address, ve.address, tetu.address);
15 | const tetuVoter = await DeployerUtils.deployTetuVoter(signer, controller.address, ve.address, tetu.address, gauge.address, bribe.address);
16 | const platformVoter = await DeployerUtils.deployPlatformVoter(signer, controller.address, ve.address);
17 | const forwarder = await DeployerUtils.deployForwarder(signer, controller.address, tetu.address, bribe.address);
18 | const fundAdr = await DeployerUtils.deployProxy(signer, 'InvestFundV2');
19 | const investFund = InvestFundV2__factory.connect(fundAdr, signer);
20 | await RunHelper.runAndWait(() => investFund.init(controller.address));
21 |
22 | const vaultImpl = await DeployerUtils.deployContract(signer, 'TetuVaultV2');
23 | const vaultInsuranceImpl = await DeployerUtils.deployContract(signer, 'VaultInsurance');
24 | const splitterImpl = await DeployerUtils.deployContract(signer, 'StrategySplitterV2');
25 |
26 | const vaultFactory = await DeployerUtils.deployVaultFactory(
27 | signer,
28 | controller.address,
29 | vaultImpl.address,
30 | vaultInsuranceImpl.address,
31 | splitterImpl.address,
32 | );
33 |
34 | await RunHelper.runAndWait(() => controller.announceAddressChange(2, tetuVoter.address)); // TETU_VOTER
35 | await RunHelper.runAndWait(() => controller.announceAddressChange(3, platformVoter.address)); // PLATFORM_VOTER
36 | // await controller.announceAddressChange(4, .address); // LIQUIDATOR
37 | await RunHelper.runAndWait(() => controller.announceAddressChange(5, forwarder.address)); // FORWARDER
38 | await RunHelper.runAndWait(() => controller.announceAddressChange(6, fundAdr)); // INVEST_FUND
39 | await RunHelper.runAndWait(() => controller.announceAddressChange(7, signer.address)); // VE_DIST
40 |
41 |
42 | await RunHelper.runAndWait(() => controller.changeAddress(2)); // TETU_VOTER
43 | await RunHelper.runAndWait(() => controller.changeAddress(3)); // PLATFORM_VOTER
44 | // await controller.changeAddress(4); // LIQUIDATOR
45 | await RunHelper.runAndWait(() => controller.changeAddress(5)); // FORWARDER
46 | await RunHelper.runAndWait(() => controller.changeAddress(6)); // INVEST_FUND
47 | await RunHelper.runAndWait(() => controller.changeAddress(7)); // VE_DIST
48 |
49 | const result = `
50 | tetu: ${tetu.address}
51 | controller: ${controller.address}
52 | ve: ${ve.address}
53 | veDist: ${veDist.address}
54 | gauge: ${gauge.address}
55 | bribe: ${bribe.address}
56 | tetuVoter: ${tetuVoter.address}
57 | platformVoter: ${platformVoter.address}
58 | forwarder: ${forwarder.address}
59 | vaultFactory: ${vaultFactory.address}
60 | `;
61 | writeFileSync('tmp/deployed/core.txt', result, 'utf8');
62 | }
63 |
64 | main()
65 | .then(() => process.exit(0))
66 | .catch(error => {
67 | console.error(error);
68 | process.exit(1);
69 | });
70 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployBribeDistribution.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {Addresses} from "../addresses/addresses";
4 | import {BribeDistribution} from "../../typechain";
5 |
6 | async function main() {
7 | const signer = (await ethers.getSigners())[0];
8 | const core = Addresses.getCore();
9 | await DeployerUtils.deployContract(signer, "BribeDistribution", core.veDist, core.tetu);
10 | }
11 |
12 | main()
13 | .then(() => process.exit(0))
14 | .catch(error => {
15 | console.error(error);
16 | process.exit(1);
17 | });
18 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployDepositHelperBaseChain.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {BaseAddresses} from "../addresses/base";
4 |
5 | async function main() {
6 | const signer = (await ethers.getSigners())[0];
7 | await DeployerUtils.deployContract(signer, 'DepositHelperBaseChain', BaseAddresses.ONE_INCH_ROUTER_V5);
8 | }
9 |
10 | main()
11 | .then(() => process.exit(0))
12 | .catch(error => {
13 | console.error(error);
14 | process.exit(1);
15 | });
16 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployDepositHelperPolygon.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {PolygonAddresses} from "../addresses/polygon";
4 |
5 | async function main() {
6 | const signer = (await ethers.getSigners())[0];
7 | await DeployerUtils.deployContract(signer, 'DepositHelperPolygon', PolygonAddresses.ONE_INCH_ROUTER_V5);
8 | }
9 |
10 | main()
11 | .then(() => process.exit(0))
12 | .catch(error => {
13 | console.error(error);
14 | process.exit(1);
15 | });
16 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployForwarderResolver.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {appendFileSync} from "fs";
4 | import {Addresses} from "../addresses/addresses";
5 | import {ForwarderDistributeResolver__factory, HardWorkResolver__factory} from "../../typechain";
6 | import {RunHelper} from "../utils/RunHelper";
7 |
8 |
9 | async function main() {
10 | const signer = (await ethers.getSigners())[0];
11 | const core = Addresses.getCore();
12 | const contract = await DeployerUtils.deployProxy(signer, 'ForwarderDistributeResolver');
13 | await RunHelper.runAndWait(() => ForwarderDistributeResolver__factory.connect(contract, signer).init(core.controller));
14 | }
15 |
16 | main()
17 | .then(() => process.exit(0))
18 | .catch(error => {
19 | console.error(error);
20 | process.exit(1);
21 | });
22 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployHardworkResolver.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {appendFileSync} from "fs";
4 | import {Addresses} from "../addresses/addresses";
5 | import {HardWorkResolver__factory} from "../../typechain";
6 | import {RunHelper} from "../utils/RunHelper";
7 |
8 |
9 | async function main() {
10 | const signer = (await ethers.getSigners())[0];
11 | const core = Addresses.getCore();
12 | const contract = await DeployerUtils.deployProxy(signer, 'HardWorkResolver');
13 | await RunHelper.runAndWait(() => HardWorkResolver__factory.connect(contract, signer).init(core.controller));
14 | }
15 |
16 | main()
17 | .then(() => process.exit(0))
18 | .catch(error => {
19 | console.error(error);
20 | process.exit(1);
21 | });
22 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployInvestFund.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {InvestFundV2__factory} from "../../typechain";
4 | import {Addresses} from "../addresses/addresses";
5 |
6 |
7 | async function main() {
8 | const signer = (await ethers.getSigners())[0];
9 | const core = Addresses.getCore();
10 | const fundAdr = await DeployerUtils.deployProxy(signer, 'InvestFundV2');
11 | const investFund = InvestFundV2__factory.connect(fundAdr, signer);
12 | await investFund.init(core.controller);
13 | }
14 |
15 | main()
16 | .then(() => process.exit(0))
17 | .catch(error => {
18 | console.error(error);
19 | process.exit(1);
20 | });
21 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployMockStrategy.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {RunHelper} from "../utils/RunHelper";
4 | import {MockStrategy, MockStrategy__factory, StrategySplitterV2__factory} from "../../typechain";
5 | import {Addresses} from "../addresses/addresses";
6 |
7 | const SPLITTER = '0x24dc9f1b9ae0fA62acb120Ea77D7fC89C6814F72';
8 |
9 | async function main() {
10 | const signer = (await ethers.getSigners())[0];
11 |
12 | const strategy1 = MockStrategy__factory.connect(await DeployerUtils.deployProxy(signer, 'MockStrategy'), signer);
13 | await setupStrategy(strategy1)
14 |
15 | const strategy2 = MockStrategy__factory.connect(await DeployerUtils.deployProxy(signer, 'MockStrategy'), signer);
16 | await setupStrategy(strategy2)
17 |
18 | const strategy3 = MockStrategy__factory.connect(await DeployerUtils.deployProxy(signer, 'MockStrategy'), signer);
19 | await setupStrategy(strategy3)
20 |
21 | const splitter = StrategySplitterV2__factory.connect(SPLITTER, signer);
22 | await RunHelper.runAndWait(() => splitter.addStrategies(
23 | [strategy1.address, strategy2.address, strategy3.address],
24 | [Math.round(Math.random() * 100), Math.round(Math.random() * 200), Math.round(Math.random() * 2)],
25 | [0, 0, 0]
26 | ));
27 | }
28 |
29 | main()
30 | .then(() => process.exit(0))
31 | .catch(error => {
32 | console.error(error);
33 | process.exit(1);
34 | });
35 |
36 |
37 | async function setupStrategy(strategy: MockStrategy) {
38 | const core = Addresses.getCore();
39 | await RunHelper.runAndWait(() => strategy.init(
40 | core.controller,
41 | SPLITTER
42 | ));
43 |
44 | await RunHelper.runAndWait(() => strategy.setSlippage(Math.round(Math.random() * 500)));
45 | await RunHelper.runAndWait(() => strategy.setSlippageDeposit(Math.round(Math.random() * 500)));
46 | await RunHelper.runAndWait(() => strategy.setSlippageHardWork(Math.round(Math.random() * 500)));
47 | await RunHelper.runAndWait(() => strategy.setLast(Math.round(Math.random() * 1000_000), 0));
48 | }
49 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployMockToken.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {appendFileSync} from "fs";
4 |
5 |
6 | async function main() {
7 | const signer = (await ethers.getSigners())[0];
8 | await DeployerUtils.deployMockToken(signer, 'WETH', 18);
9 | }
10 |
11 | main()
12 | .then(() => process.exit(0))
13 | .catch(error => {
14 | console.error(error);
15 | process.exit(1);
16 | });
17 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployPerfFeeTreasury.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {PolygonAddresses} from "../addresses/polygon";
4 |
5 | async function main() {
6 | const signer = (await ethers.getSigners())[0];
7 | await DeployerUtils.deployContract(signer, 'PerfFeeTreasury', '0x0644141dd9c2c34802d28d334217bd2034206bf7');
8 | }
9 |
10 | main()
11 | .then(() => process.exit(0))
12 | .catch(error => {
13 | console.error(error);
14 | process.exit(1);
15 | });
16 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployRewardsRedirector.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {appendFileSync} from "fs";
4 | import {Addresses} from "../addresses/addresses";
5 | import {ForwarderDistributeResolver__factory, HardWorkResolver__factory} from "../../typechain";
6 | import {RunHelper} from "../utils/RunHelper";
7 |
8 |
9 | async function main() {
10 | const signer = (await ethers.getSigners())[0];
11 | const core = Addresses.getCore();
12 | await DeployerUtils.deployContract(signer, 'RewardsRedirector', '0x0644141dd9c2c34802d28d334217bd2034206bf7', core.gauge);
13 | }
14 |
15 | main()
16 | .then(() => process.exit(0))
17 | .catch(error => {
18 | console.error(error);
19 | process.exit(1);
20 | });
21 |
--------------------------------------------------------------------------------
/scripts/deploy/DeploySplitterRebalanceResolver.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {appendFileSync} from "fs";
4 | import {Addresses} from "../addresses/addresses";
5 | import {HardWorkResolver__factory, SplitterRebalanceResolver__factory} from "../../typechain";
6 | import {RunHelper} from "../utils/RunHelper";
7 |
8 |
9 | async function main() {
10 | const signer = (await ethers.getSigners())[0];
11 | const core = Addresses.getCore();
12 | const contract = await DeployerUtils.deployProxy(signer, 'SplitterRebalanceResolver');
13 | await RunHelper.runAndWait(() => SplitterRebalanceResolver__factory.connect(contract, signer).init(core.controller));
14 | }
15 |
16 | main()
17 | .then(() => process.exit(0))
18 | .catch(error => {
19 | console.error(error);
20 | process.exit(1);
21 | });
22 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployTetuBridgedProcessing.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {TetuBridgedProcessing} from "../../typechain";
4 | import {PolygonAddresses} from "../addresses/polygon";
5 |
6 |
7 | async function main() {
8 | const signer = (await ethers.getSigners())[0];
9 | await DeployerUtils.deployContract(signer, 'TetuBridgedProcessing', PolygonAddresses.TETU_TOKEN, PolygonAddresses.fxTETU_TOKEN, PolygonAddresses.GOVERNANCE);
10 | }
11 |
12 | main()
13 | .then(() => process.exit(0))
14 | .catch(error => {
15 | console.error(error);
16 | process.exit(1);
17 | });
18 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployVault.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Addresses} from "../addresses/addresses";
3 | import {
4 | ControllerV2__factory,
5 | IERC20Metadata__factory,
6 | MultiGauge__factory,
7 | TetuVaultV2__factory,
8 | VaultFactory__factory
9 | } from "../../typechain";
10 | import {RunHelper} from "../utils/RunHelper";
11 | import {BaseAddresses} from "../addresses/base";
12 | import {ZkEvmAddresses} from "../addresses/zkevm";
13 |
14 |
15 | const ASSET = ZkEvmAddresses.USDC_TOKEN;
16 | const BUFFER = 1000; // 1%
17 | const DEPOSIT_FEE = 300; // 0.3%
18 | const WITHDRAW_FEE = 300; // 0.3%
19 |
20 | async function main() {
21 | const signer = (await ethers.getSigners())[0];
22 | const core = Addresses.getCore();
23 |
24 | const symbol = await IERC20Metadata__factory.connect(ASSET, signer).symbol();
25 | const vaultSymbol = "t" + symbol;
26 |
27 | const factory = VaultFactory__factory.connect(core.vaultFactory, signer)
28 |
29 | await RunHelper.runAndWait2(factory.populateTransaction.createVault(
30 | ASSET,
31 | 'Tetu V2 ' + vaultSymbol,
32 | vaultSymbol,
33 | core.gauge,
34 | BUFFER
35 | ));
36 | const l = (await factory.deployedVaultsLength()).toNumber();
37 | const vault = await factory.deployedVaults(l - 1);
38 | console.log(l, 'VAULT: ', vault)
39 |
40 | await RunHelper.runAndWait2(TetuVaultV2__factory.connect(vault, signer).populateTransaction.setFees(DEPOSIT_FEE, WITHDRAW_FEE));
41 | await RunHelper.runAndWait2(ControllerV2__factory.connect(core.controller, signer).populateTransaction.registerVault(vault));
42 | await RunHelper.runAndWait2(MultiGauge__factory.connect(core.gauge, signer).populateTransaction.addStakingToken(vault));
43 | }
44 |
45 | main()
46 | .then(() => process.exit(0))
47 | .catch(error => {
48 | console.error(error);
49 | process.exit(1);
50 | });
51 |
--------------------------------------------------------------------------------
/scripts/deploy/DeployVaultFactory.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {DeployerUtils} from "../utils/DeployerUtils";
3 | import {appendFileSync} from "fs";
4 | import {Addresses} from "../addresses/addresses";
5 |
6 |
7 | async function main() {
8 | const signer = (await ethers.getSigners())[0];
9 | const core = Addresses.getCore();
10 | await DeployerUtils.deployVaultFactory(
11 | signer,
12 | core.controller,
13 | '0xa2c5911b6ecb4da440c93f8b7daa90c68f53e26a',
14 | '0x6d85966b5280bfbb479e0eba00ac5cedfe8760d3',
15 | '0x27af55366a339393865fc5943c04bc2600f55c9f',
16 | );
17 | }
18 |
19 | main()
20 | .then(() => process.exit(0))
21 | .catch(error => {
22 | console.error(error);
23 | process.exit(1);
24 | });
25 |
--------------------------------------------------------------------------------
/scripts/gov/execute-upgrades.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Addresses} from "../addresses/addresses";
3 | import {ControllerV2__factory} from "../../typechain";
4 | import {RunHelper} from "../utils/RunHelper";
5 |
6 | // tslint:disable-next-line:no-var-requires
7 | const hre = require("hardhat");
8 |
9 |
10 | async function main() {
11 | const [signer] = await ethers.getSigners();
12 | const core = Addresses.getCore();
13 | const toUpdate = await ControllerV2__factory.connect(core.controller, signer).proxyAnnouncesList()
14 |
15 | if (toUpdate.length === 0) {
16 | return;
17 | }
18 |
19 | for (const u of toUpdate) {
20 | console.log('Update ', u.proxy, ' to ', u.implementation, new Date(u.timeLockAt.toNumber() * 1000));
21 | }
22 |
23 | const proxiesReadyToUpgrade = toUpdate
24 | .filter(u => u.timeLockAt.toNumber() * 1000 < Date.now())
25 | .map(u => u.proxy);
26 |
27 | for (const u of proxiesReadyToUpgrade) {
28 | console.log('READY to Update ', u);
29 | }
30 |
31 | console.log('Ready to Update ', proxiesReadyToUpgrade);
32 | if (proxiesReadyToUpgrade.length !== 0) {
33 | await RunHelper.runAndWait2(ControllerV2__factory.connect(core.controller, signer).populateTransaction.upgradeProxy(proxiesReadyToUpgrade));
34 | }
35 |
36 |
37 | }
38 |
39 | main()
40 | .then(() => process.exit(0))
41 | .catch(error => {
42 | console.error(error);
43 | process.exit(1);
44 | });
45 |
--------------------------------------------------------------------------------
/scripts/gov/poke-gauge-voter.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Addresses} from "../addresses/addresses";
3 | import {TetuVoter__factory} from "../../typechain";
4 | import {RunHelper} from "../utils/RunHelper";
5 | import {txParams} from "../deploy/DeployContract";
6 |
7 | // tslint:disable-next-line:no-var-requires
8 | const {request, gql} = require('graphql-request')
9 |
10 | // tslint:disable-next-line:no-var-requires
11 | const hre = require("hardhat");
12 |
13 | async function main() {
14 | const [signer] = await ethers.getSigners();
15 | const core = Addresses.getCore();
16 |
17 | // const gov = await Misc.impersonate('0xcc16d636dD05b52FF1D8B9CE09B09BC62b11412B')
18 | // const logic = await deployContract(hre, signer, 'TetuVoter');
19 | // await ControllerV2__factory.connect(core.controller, gov).announceProxyUpgrade([core.tetuVoter], [logic.address]);
20 | // await TimeUtils.advanceBlocksOnTs(60 * 60 * 24 * 2);
21 | // await ControllerV2__factory.connect(core.controller, gov).upgradeProxy([core.tetuVoter]);
22 |
23 | const voter = TetuVoter__factory.connect(core.tetuVoter, signer);
24 |
25 | const data = await request('https://api.thegraph.com/subgraphs/name/tetu-io/tetu-v2', gql`
26 | query tetuVoterUserVotes {
27 | tetuVoterUserVotes {
28 | date
29 | percent
30 | weight
31 | user {
32 | veNFT {
33 | veNFTId
34 | }
35 | }
36 | }
37 | }
38 | `);
39 |
40 | const votes = data.tetuVoterUserVotes;
41 |
42 | const minDate = new Map()
43 | let totalWeight = 0;
44 | for (const vote of votes) {
45 | // console.log(vote)
46 | const veId = vote.user.veNFT.veNFTId;
47 | console.log(new Date(vote.date * 1000), 'percent: ', (+vote.percent).toFixed(2), 'weight: ', Number(vote.weight).toFixed(), 've: ', veId);
48 | const md = minDate.get(+veId) ?? Date.now();
49 | totalWeight += +vote.weight;
50 | if (md > +vote.date && +vote.weight > 10_000) {
51 | minDate.set(+veId, +vote.date);
52 | }
53 | }
54 |
55 | console.log('total ve voted', totalWeight.toFixed(), minDate.size);
56 |
57 | const vePokes: number[] = [];
58 | for (const [veId, md] of minDate.entries()) {
59 | console.log('ve: ', veId, 'min date: ', new Date(md * 1000));
60 | const time = Date.now() - 60 * 60 * 24 * 21 * 1000;
61 | if (md * 1000 < time) {
62 | vePokes.push(veId);
63 | }
64 | }
65 |
66 | console.log('total ve pokes', vePokes.length);
67 |
68 | const skipVe = new Set([]);
69 |
70 | for (const veId of vePokes) {
71 | console.log('poke ve: ', veId);
72 | if (skipVe.has(veId)) {
73 | continue;
74 | }
75 | const params = await txParams(hre, ethers.provider);
76 | await RunHelper.runAndWait(() => voter.poke(veId, {...params}));
77 | }
78 |
79 | }
80 |
81 | main()
82 | .then(() => process.exit(0))
83 | .catch(error => {
84 | console.error(error);
85 | process.exit(1);
86 | });
87 |
--------------------------------------------------------------------------------
/scripts/gov/poke-platform-voter.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Addresses} from "../addresses/addresses";
3 | import {ControllerV2__factory, PlatformVoter__factory} from "../../typechain";
4 | import {RunHelper} from "../utils/RunHelper";
5 | import {deployContract, txParams} from "../deploy/DeployContract";
6 | import {Misc} from "../utils/Misc";
7 | import {TimeUtils} from "../../test/TimeUtils";
8 |
9 | // tslint:disable-next-line:no-var-requires
10 | const {request, gql} = require('graphql-request')
11 |
12 | // tslint:disable-next-line:no-var-requires
13 | const hre = require("hardhat");
14 |
15 | async function main() {
16 | const [signer] = await ethers.getSigners();
17 | const core = Addresses.getCore();
18 |
19 | // const gov = await Misc.impersonate('0xcc16d636dD05b52FF1D8B9CE09B09BC62b11412B')
20 | // const logic = await deployContract(hre, signer, 'PlatformVoter');
21 | // await ControllerV2__factory.connect(core.controller, gov).announceProxyUpgrade([core.platformVoter], [logic.address]);
22 | // await TimeUtils.advanceBlocksOnTs(60 * 60 * 24 * 2);
23 | // await ControllerV2__factory.connect(core.controller, gov).upgradeProxy([core.platformVoter]);
24 |
25 |
26 | const voter = PlatformVoter__factory.connect(core.platformVoter, signer);
27 |
28 | const data = await request('https://api.thegraph.com/subgraphs/name/tetu-io/tetu-v2', gql`
29 | query {
30 | platformVoterEntities {
31 | votes(first: 1000) {
32 | desiredValue
33 | date
34 | newValue
35 | percent
36 | target
37 | voteType
38 | veWeightedValue
39 | vePower
40 | veNFT {
41 | veNFTId
42 | }
43 | }
44 | }
45 | }
46 | `);
47 |
48 | const votes = data.platformVoterEntities[0].votes;
49 |
50 | const minDate = new Map()
51 | for (const vote of votes) {
52 | const md = minDate.get(+vote.veNFT.veNFTId) ?? Date.now();
53 | if (md > +vote.date) {
54 | // console.log(new Date(vote.date * 1000), 'value: ', vote.newValue, 'power: ', Number(vote.vePower).toFixed(), 've: ', vote.veNFT.veNFTId);
55 | minDate.set(+vote.veNFT.veNFTId, +vote.date);
56 | }
57 | }
58 |
59 | console.log('total ve voted', minDate.size);
60 |
61 | const vePokes: number[] = [];
62 | for (const [veId, md] of minDate.entries()) {
63 | const time = Date.now() - 60 * 60 * 24 * 21 * 1000;
64 | if (md * 1000 < time) {
65 | console.log('ve: ', veId, 'min date: ', new Date(md * 1000));
66 | vePokes.push(veId);
67 | }
68 | }
69 |
70 | console.log('total ve pokes', vePokes.length);
71 |
72 | const skipVe = new Set([]);
73 |
74 | for (const veId of vePokes) {
75 | console.log('poke ve: ', veId);
76 | if (skipVe.has(veId)) {
77 | continue;
78 | }
79 | const params = await txParams(hre, ethers.provider);
80 | await RunHelper.runAndWait(() => voter.poke(veId, {...params}));
81 | }
82 |
83 | }
84 |
85 | main()
86 | .then(() => process.exit(0))
87 | .catch(error => {
88 | console.error(error);
89 | process.exit(1);
90 | });
91 |
--------------------------------------------------------------------------------
/scripts/models/CoreAddresses.ts:
--------------------------------------------------------------------------------
1 | export class CoreAddresses {
2 |
3 | public readonly tetu: string;
4 | public readonly controller: string;
5 | public readonly ve: string;
6 | public readonly veDist: string;
7 | public readonly gauge: string;
8 | public readonly bribe: string;
9 | public readonly tetuVoter: string;
10 | public readonly platformVoter: string;
11 | public readonly forwarder: string;
12 | public readonly vaultFactory: string;
13 | public readonly investFundV2: string;
14 |
15 |
16 | constructor(tetu: string, controller: string, ve: string, veDist: string, gauge: string, bribe: string, tetuVoter: string, platformVoter: string, forwarder: string, vaultFactory: string, investFundV2: string) {
17 | this.tetu = tetu;
18 | this.controller = controller;
19 | this.ve = ve;
20 | this.veDist = veDist;
21 | this.gauge = gauge;
22 | this.bribe = bribe;
23 | this.tetuVoter = tetuVoter;
24 | this.platformVoter = platformVoter;
25 | this.forwarder = forwarder;
26 | this.vaultFactory = vaultFactory;
27 | this.investFundV2 = investFundV2;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/scripts/models/ToolsAddresses.ts:
--------------------------------------------------------------------------------
1 | export class ToolsAddresses {
2 |
3 | public readonly liquidator: string;
4 | public readonly converter: string;
5 | public readonly multicall: string;
6 |
7 |
8 | constructor(liquidator: string, converter: string, multicall: string) {
9 | this.liquidator = liquidator;
10 | this.converter = converter;
11 | this.multicall = multicall;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/scripts/test/CreateMockPair.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Addresses} from "../addresses/addresses";
3 | import {
4 | ControllerV2__factory,
5 | IERC20Metadata__factory,
6 | MultiGauge__factory,
7 | VaultFactory__factory
8 | } from "../../typechain";
9 | import {RunHelper} from "../utils/RunHelper";
10 |
11 |
12 | const TOKEN0 = '0x27af55366a339393865FC5943C04bc2600F55C9F';
13 | const TOKEN1 = '0x0ed08c9A2EFa93C4bF3C8878e61D2B6ceD89E9d7';
14 | const FACTORY = '0xB6Ca119F30B3E7F6589F8a053c2a10B753846e78';
15 |
16 | async function main() {
17 | const signer = (await ethers.getSigners())[0];
18 |
19 | }
20 |
21 | main()
22 | .then(() => process.exit(0))
23 | .catch(error => {
24 | console.error(error);
25 | process.exit(1);
26 | });
27 |
--------------------------------------------------------------------------------
/scripts/test/MakeNoizeOnTestnet.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {
3 | ControllerV2__factory,
4 | IERC20__factory,
5 | MultiBribe__factory,
6 | MultiGauge__factory,
7 | StakelessMultiPoolBase__factory,
8 | TetuVoter__factory,
9 | VeTetu__factory
10 | } from "../../typechain";
11 | import {Addresses} from "../addresses/addresses";
12 | import {formatUnits, parseUnits} from "ethers/lib/utils";
13 | import {RunHelper} from "../utils/RunHelper";
14 | import {Misc} from "../utils/Misc";
15 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
16 |
17 | const USDC = '0x27af55366a339393865FC5943C04bc2600F55C9F';
18 | const BTC = '0x0ed08c9A2EFa93C4bF3C8878e61D2B6ceD89E9d7';
19 | const WETH = '0x078b7c9304eBA754e916016E8A8939527076f991';
20 |
21 | async function main() {
22 | const signer = (await ethers.getSigners())[0];
23 | const core = Addresses.getCore();
24 |
25 | const vaults = await ControllerV2__factory.connect(core.controller, signer).vaultsList();
26 |
27 | const bribe = MultiBribe__factory.connect(core.bribe, signer);
28 | const gauge = MultiGauge__factory.connect(core.gauge, signer);
29 |
30 | for (const vault of vaults) {
31 |
32 | await registerTokenIfnOtExist(signer, gauge.address, vault, USDC);
33 | const gaugeLeft = await gauge.left(vault, USDC)
34 | if (gaugeLeft.lt(parseUnits('1', 6))) {
35 | await RunHelper.runAndWait(() => gauge.notifyRewardAmount(vault, USDC, parseUnits('1', 6)));
36 | }
37 |
38 | await registerTokenIfnOtExist(signer, bribe.address, vault, WETH);
39 | const bribeLeft = await bribe.left(vault, WETH)
40 | if (bribeLeft.lt(parseUnits('1'))) {
41 | await RunHelper.runAndWait(() => bribe.notifyRewardAmount(vault, WETH, parseUnits('1')))
42 | }
43 | const veBalance = await VeTetu__factory.connect(core.ve, signer).balanceOf(signer.address);
44 | console.log('ve balance', veBalance.toString());
45 | for (let i = 0; i < veBalance.toNumber(); i++) {
46 | if (!veBalance.isZero()) {
47 | const veId = (await VeTetu__factory.connect(core.ve, signer).tokenOfOwnerByIndex(signer.address, i)).toNumber()
48 | const power = await VeTetu__factory.connect(core.ve, signer).balanceOfNFT(veId)
49 | console.log('veId', veId, formatUnits(power))
50 | if (!power.isZero()) {
51 |
52 | const voter = TetuVoter__factory.connect(core.tetuVoter, signer);
53 | const lastVote = (await voter.lastVote(veId)).toNumber();
54 | console.log('lastVote', new Date(lastVote * 1000))
55 | if ((lastVote + 60 * 60 * 24 * 7) < (Date.now() / 1000)) {
56 | await RunHelper.runAndWait(() => voter.vote(veId, [vault], [100]));
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
63 | }
64 |
65 | async function registerTokenIfnOtExist(signer: SignerWithAddress, pool: string, vault: string, token: string) {
66 | const poolCtr = StakelessMultiPoolBase__factory.connect(pool, signer);
67 | const rtLength = (await poolCtr.rewardTokensLength(vault)).toNumber();
68 | const rts = new Set();
69 | for (let i = 0; i < rtLength; i++) {
70 | const rt = await poolCtr.rewardTokens(vault, i);
71 | rts.add(rt.toLowerCase());
72 | }
73 | if (!rts.has(token.toLowerCase())) {
74 | await RunHelper.runAndWait(() => poolCtr.registerRewardToken(vault, token));
75 | }
76 |
77 | const allowance = await IERC20__factory.connect(token, signer).allowance(signer.address, pool)
78 | if (allowance.lt(parseUnits('100'))) {
79 | await RunHelper.runAndWait(() => IERC20__factory.connect(token, signer).approve(pool, Misc.MAX_UINT));
80 | }
81 | }
82 |
83 | main()
84 | .then(() => process.exit(0))
85 | .catch(error => {
86 | console.error(error);
87 | process.exit(1);
88 | });
89 |
--------------------------------------------------------------------------------
/scripts/utils/Misc.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Logger} from "tslog";
3 | import Common from "ethereumjs-common";
4 | import logSettings from "../../log_settings";
5 |
6 | const log: Logger = new Logger(logSettings);
7 |
8 | const MATIC_CHAIN = Common.forCustomChain(
9 | 'mainnet', {
10 | name: 'matic',
11 | networkId: 137,
12 | chainId: 137
13 | },
14 | 'petersburg'
15 | );
16 |
17 | const FANTOM_CHAIN = Common.forCustomChain(
18 | 'mainnet', {
19 | name: 'fantom',
20 | networkId: 250,
21 | chainId: 250
22 | },
23 | 'petersburg'
24 | );
25 |
26 | // tslint:disable-next-line:no-var-requires
27 | const hre = require("hardhat");
28 |
29 | export class Misc {
30 | public static readonly SECONDS_OF_DAY = 60 * 60 * 24;
31 | public static readonly SECONDS_OF_YEAR = Misc.SECONDS_OF_DAY * 365;
32 | public static readonly ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
33 | public static readonly MAX_UINT = '115792089237316195423570985008687907853269984665640564039457584007913129639935';
34 | public static readonly MAX_UINT_MINUS_ONE = '115792089237316195423570985008687907853269984665640564039457584007913129639934';
35 |
36 | public static printDuration(text: string, start: number) {
37 | log.info('>>>' + text, ((Date.now() - start) / 1000).toFixed(1), 'sec');
38 | }
39 |
40 | // public static async getBlockTsFromChain(): Promise {
41 | // const signer = (await ethers.getSigners())[0];
42 | // const tools = await DeployerUtils.getToolsAddresses();
43 | // const ctr = await DeployerUtils.connectInterface(signer, 'Multicall', tools.multicall) as Multicall;
44 | // const ts = await ctr.getCurrentBlockTimestamp();
45 | // return ts.toNumber();
46 | // }
47 |
48 | public static async getChainConfig() {
49 | const net = await ethers.provider.getNetwork();
50 | switch (net.chainId) {
51 | case 137:
52 | return MATIC_CHAIN;
53 | case 250:
54 | return FANTOM_CHAIN;
55 | default:
56 | throw new Error('Unknown net ' + net.chainId)
57 | }
58 | }
59 |
60 | // ************** ADDRESSES **********************
61 |
62 | public static async impersonate(address: string) {
63 | await hre.network.provider.request({
64 | method: "hardhat_impersonateAccount",
65 | params: [address],
66 | });
67 |
68 | await hre.network.provider.request({
69 | method: "hardhat_setBalance",
70 | params: [address, "0x1431E0FAE6D7217CAA0000000"],
71 | });
72 | // console.log('address impersonated', address);
73 | return ethers.getSigner(address);
74 | }
75 |
76 | public static isNotNetwork(id: number) {
77 | return hre.network.config.chainId !== id;
78 | }
79 |
80 | public static async getStorageAt(address: string, index: string) {
81 | return ethers.provider.getStorageAt(address, index);
82 | }
83 |
84 | public static async setStorageAt(address: string, index: string, value: string) {
85 | await ethers.provider.send("hardhat_setStorageAt", [address, index, value]);
86 | await ethers.provider.send("evm_mine", []); // Just mines to the next block
87 | }
88 |
89 | // ****************** WAIT ******************
90 |
91 | public static async delay(ms: number) {
92 | return new Promise(resolve => setTimeout(resolve, ms));
93 | }
94 |
95 | public static async wait(blocks: number) {
96 | if (hre.network.name === 'hardhat') {
97 | return;
98 | }
99 | const start = ethers.provider.blockNumber;
100 | while (true) {
101 | log.info('wait 10sec');
102 | await Misc.delay(10000);
103 | if (ethers.provider.blockNumber >= start + blocks) {
104 | break;
105 | }
106 | }
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/scripts/utils/UpdateBlock.ts:
--------------------------------------------------------------------------------
1 | import {fetchJson} from "ethers/lib/utils";
2 | import * as fs from "fs";
3 |
4 | const _getBlockUrl = 'https://api.polygonscan.com/api?module=proxy&action=eth_blockNumber';
5 | const _envFilename = '.env'
6 | const _envParamName = 'TETU_MATIC_FORK_BLOCK';
7 |
8 | async function updateBlockNumber(url: string, envFilename: string, envParamName: string) {
9 | const blockData = await fetchJson({url});
10 | const blockNumber = Number(blockData.result) - 32; // hardhat needs block that has at least 32 confirmations
11 | replaceParamInEnvFile(envFilename, envParamName, blockNumber.toString());
12 | console.log(_envParamName, 'replaced to', blockNumber, 'in file', envFilename);
13 | }
14 |
15 | function replaceParamInEnvFile(envFileName: string,envParamName: string, newValue: string) {
16 | const envContent = fs.readFileSync(envFileName).toString();
17 | const pattern = new RegExp(`^${envParamName}=.+$`, 'm');
18 | const newContent = envContent.replace(pattern, envParamName+'='+newValue);
19 | fs.writeFileSync(envFileName, newContent);
20 | }
21 |
22 | updateBlockNumber(_getBlockUrl, _envFilename, _envParamName).then();
23 |
--------------------------------------------------------------------------------
/scripts/utils/VerifyUtils.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import axios from "axios";
3 | import {config as dotEnvConfig} from "dotenv";
4 | import logSettings from "../../log_settings";
5 | import {Logger} from "tslog";
6 |
7 | // tslint:disable-next-line:no-var-requires
8 | const hre = require("hardhat");
9 | const log: Logger = new Logger(logSettings);
10 |
11 |
12 | dotEnvConfig();
13 | // tslint:disable-next-line:no-var-requires
14 | const argv = require('yargs/yargs')()
15 | .env('TETU')
16 | .options({
17 | networkScanKey: {
18 | type: "string",
19 | },
20 | }).argv;
21 |
22 |
23 | export class VerifyUtils {
24 |
25 |
26 | public static async verify(address: string) {
27 | try {
28 | await hre.run("verify:verify", {
29 | address
30 | })
31 | } catch (e) {
32 | log.info('error verify ' + e);
33 | }
34 | }
35 |
36 | // tslint:disable-next-line:no-any
37 | public static async verifyWithArgs(address: string, args: any[]) {
38 | try {
39 | await hre.run("verify:verify", {
40 | address, constructorArguments: args
41 | })
42 | } catch (e) {
43 | log.info('error verify ' + e);
44 | }
45 | }
46 |
47 | // tslint:disable-next-line:no-any
48 | public static async verifyWithContractName(address: string, contractPath: string, args?: any[]) {
49 | try {
50 | await hre.run("verify:verify", {
51 | address, contract: contractPath, constructorArguments: args
52 | })
53 | } catch (e) {
54 | log.info('error verify ' + e);
55 | }
56 | }
57 |
58 | // tslint:disable-next-line:no-any
59 | public static async verifyWithArgsAndContractName(address: string, args: any[], contractPath: string) {
60 | try {
61 | await hre.run("verify:verify", {
62 | address, constructorArguments: args, contract: contractPath
63 | })
64 | } catch (e) {
65 | log.info('error verify ' + e);
66 | }
67 | }
68 |
69 | public static async verifyProxy(adr: string) {
70 | try {
71 |
72 | const resp =
73 | await axios.post(
74 | (await VerifyUtils.getNetworkScanUrl()) +
75 | `?module=contract&action=verifyproxycontract&apikey=${argv.networkScanKey}`,
76 | `address=${adr}`);
77 | // log.info("proxy verify resp", resp.data);
78 | } catch (e) {
79 | log.info('error proxy verify ' + adr + e);
80 | }
81 | }
82 |
83 | public static async getNetworkScanUrl(): Promise {
84 | const net = (await ethers.provider.getNetwork());
85 | if (net.name === 'ropsten') {
86 | return 'https://api-ropsten.etherscan.io/api';
87 | } else if (net.name === 'kovan') {
88 | return 'https://api-kovan.etherscan.io/api';
89 | } else if (net.name === 'rinkeby') {
90 | return 'https://api-rinkeby.etherscan.io/api';
91 | } else if (net.name === 'ethereum') {
92 | return 'https://api.etherscan.io/api';
93 | } else if (net.name === 'matic') {
94 | return 'https://api.polygonscan.com/api'
95 | } else if (net.chainId === 80001) {
96 | return 'https://api-testnet.polygonscan.com/api'
97 | } else if (net.chainId === 250) {
98 | return 'https://api.ftmscan.com//api'
99 | } else {
100 | throw Error('network not found ' + net);
101 | }
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/scripts/utils/Web3Utils.ts:
--------------------------------------------------------------------------------
1 | import {web3} from "hardhat";
2 | import {DeployerUtils} from "./DeployerUtils";
3 |
4 | export class Web3Utils {
5 |
6 |
7 | public static async parseLogs(contract: string, topics: string[], start: number, end: number, step = 3_000) {
8 | const logs = [];
9 |
10 | console.log('parseLogs', start, end);
11 | let from = start;
12 | let to = start + step;
13 | while (true) {
14 | try {
15 | logs.push(...(await web3.eth.getPastLogs({
16 | fromBlock: from,
17 | toBlock: to,
18 | address: contract,
19 | "topics": topics
20 | })));
21 |
22 | console.log('logs', from, to, logs.length);
23 |
24 | from = to;
25 | to = Math.min(from + step, end);
26 |
27 | if (from >= end) {
28 | break;
29 | }
30 | } catch (e) {
31 | console.log('Error fetch logs', e);
32 | await DeployerUtils.delay(1000);
33 | }
34 | }
35 |
36 | return logs;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/slither.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "detectors_to_exclude": "naming-convention,low-level-calls,assembly,reentrancy-events,reentrancy-benign,divide-before-multiply,reentrancy-eth,reentrancy-no-eth,reentrancy-unlimited-gas,incorrect-equality,costly-loop,timestamp,similar-names,too-many-digits,calls-loop,solc-version",
3 | "disable_color": true,
4 | "filter_paths": "(node_modules/|contracts/test/|contracts/openzeppelin/)",
5 | "ignore_compile": true
6 | }
7 |
--------------------------------------------------------------------------------
/test/TestAsserts.ts:
--------------------------------------------------------------------------------
1 | import chai from "chai";
2 | import {BigNumber, ContractTransaction, Event, utils} from "ethers";
3 | import chaiAsPromised from "chai-as-promised";
4 |
5 | const {expect} = chai;
6 | chai.use(chaiAsPromised);
7 |
8 | export class TestAsserts {
9 |
10 | public static async assertEvent(
11 | tx: ContractTransaction,
12 | eventName: string,
13 | // tslint:disable-next-line:no-any
14 | args: any[],
15 | eIdx = 0
16 | ) {
17 | const receipt = await tx.wait();
18 |
19 | const events = receipt.events?.filter((e) => e.event === eventName) as Event[];
20 | expect(events !== undefined).is.eq(true, `Event ${eventName} not found`);
21 | const event = events[eIdx];
22 | event.args?.forEach((value, i) => {
23 | if (i + 1 > args.length) {
24 | return;
25 | }
26 | if (typeof value === 'string') {
27 | expect(typeof args[i]).is.eq('string', `Arg ${i} is not string`);
28 | expect(value.toLowerCase()).is.eq(args[i].toLowerCase(), `Arg ${i} is not equal`);
29 | } else if (value instanceof BigNumber) {
30 | expect(value.toString()).is.eq(BigNumber.from(args[i]).toString(), `Arg ${i} is not equal`);
31 | } else {
32 | expect(value).is.eq(args[i], `Arg ${i} is not equal`);
33 | }
34 | });
35 | }
36 |
37 | public static closeTo(actual: BigNumber, expected: BigNumber, deltaFactor: number, dec = 18) {
38 | const actualN = +utils.formatUnits(actual);
39 | const expectedN = +utils.formatUnits(expected);
40 | expect(actualN).to.be.closeTo(expectedN, expectedN * deltaFactor);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/test/TimeUtils.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {Misc} from "../scripts/utils/Misc";
3 | import {Multicall} from "../typechain";
4 |
5 | export const LOCK_PERIOD = 60 * 60 * 24 * 7 * 16;
6 |
7 | export class TimeUtils {
8 |
9 | public static async advanceBlocksOnTs(add: number) {
10 | const start = Date.now();
11 | // const block = await TimeUtils.currentBlock();
12 | await ethers.provider.send('evm_increaseTime', [add]);
13 | await ethers.provider.send('evm_mine', []);
14 | // await TimeUtils.mineAndCheck();
15 | Misc.printDuration('advanceBlocksOnTs ' + add + ' completed', start);
16 | }
17 |
18 | public static async advanceNBlocks(n: number) {
19 | const start = Date.now();
20 | await ethers.provider.send('evm_increaseTime', [+(n * 2.35).toFixed(0)]);
21 | for (let i = 0; i < n; i++) {
22 | await ethers.provider.send('evm_mine', []);
23 | }
24 | Misc.printDuration('advanceNBlocks ' + n + ' completed', start);
25 | }
26 |
27 | public static async mineAndCheck() {
28 | const start = ethers.provider.blockNumber;
29 | while (true) {
30 | await ethers.provider.send('evm_mine', []);
31 | if (ethers.provider.blockNumber > start) {
32 | break;
33 | }
34 | console.log('waite mine 10sec');
35 | await Misc.delay(10000);
36 | }
37 | }
38 |
39 | public static async setBlock(blockNumber: number) {
40 | await ethers.provider.send('evm_setNextBlockTimestamp', [blockNumber]);
41 | }
42 |
43 | public static async setNextBlockTime(ts: number) {
44 | await ethers.provider.send('evm_setNextBlockTimestamp', [ts]);
45 | await ethers.provider.send('evm_mine', []);
46 | }
47 |
48 | // // doesn't work, need to investigate
49 | // public static async currentBlock() {
50 | // const tools = await DeployerUtils.getToolsAddresses();
51 | // const multicall = Multicall__factory.connect(tools.multicall, ethers.provider);
52 | // const blockHash = await multicall.getLastBlockHash();
53 | // return (await ethers.provider.getBlock(blockHash)).number;
54 | // }
55 |
56 | public static async getBlockTime(multicall: Multicall, block?: number | null): Promise {
57 | if (block) {
58 | return (await multicall.getCurrentBlockTimestamp({blockTag: block})).toNumber();
59 | } else {
60 | return (await multicall.getCurrentBlockTimestamp()).toNumber();
61 | }
62 | }
63 |
64 | public static async snapshot() {
65 | const id = await ethers.provider.send("evm_snapshot", []);
66 | console.log("made snapshot", id);
67 | return id;
68 | }
69 |
70 | public static async rollback(id: string) {
71 | console.log("restore snapshot", id);
72 | return ethers.provider.send("evm_revert", [id]);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/test/TokenUtils.ts:
--------------------------------------------------------------------------------
1 | import {IERC20__factory, MockToken__factory} from "../typechain";
2 | import {BigNumber} from "ethers";
3 | import {PolygonAddresses as MaticAddresses} from "../scripts/addresses/polygon";
4 | import {parseUnits} from "ethers/lib/utils";
5 | import {Misc} from "../scripts/utils/Misc";
6 | import {BaseAddresses} from "../scripts/addresses/base";
7 |
8 | export class TokenUtils {
9 |
10 | // use the most neutral place, some contracts (like swap pairs) can be used in tests and direct transfer ruin internal logic
11 | public static TOKEN_HOLDERS = new Map([
12 | [MaticAddresses.WMATIC_TOKEN, '0x8df3aad3a84da6b69a4da8aec3ea40d9091b2ac4'.toLowerCase()], // aave
13 | [MaticAddresses.WETH_TOKEN, '0x28424507fefb6f7f8e9d3860f56504e4e5f5f390'.toLowerCase()], // aave
14 | [MaticAddresses.WBTC_TOKEN, '0x5c2ed810328349100a66b82b78a1791b101c9d61'.toLowerCase()], // aave v2
15 | [MaticAddresses.USDC_TOKEN, '0x1a13f4ca1d028320a707d99520abfefca3998b7f'.toLowerCase()], // aave
16 | [MaticAddresses.USDT_TOKEN, '0x0D0707963952f2fBA59dD06f2b425ace40b492Fe'.toLowerCase()], // adr
17 | [MaticAddresses.TETU_TOKEN, '0x7ad5935ea295c4e743e4f2f5b4cda951f41223c2'.toLowerCase()], // fund keeper
18 | [MaticAddresses.AAVE_TOKEN, '0x1d2a0e5ec8e5bbdca5cb219e649b565d8e5c3360'.toLowerCase()], // aave
19 | [MaticAddresses.DAI_TOKEN, '0xBA12222222228d8Ba445958a75a0704d566BF2C8'.toLowerCase()], // balancer
20 | [MaticAddresses.LINK_TOKEN, '0xBA12222222228d8Ba445958a75a0704d566BF2C8'.toLowerCase()], // balancer
21 | [MaticAddresses.BAL_TOKEN, '0xBA12222222228d8Ba445958a75a0704d566BF2C8'.toLowerCase()], // balancer
22 | [MaticAddresses.QI_TOKEN, '0x3FEACf904b152b1880bDE8BF04aC9Eb636fEE4d8'.toLowerCase()], // qidao gov
23 | [MaticAddresses.xTETU, '0x352f9fa490a86f625f53e581f0ec3bd649fd8bc9'.toLowerCase()],
24 | [MaticAddresses.BALANCER_TETU_USDC, '0x2F5294b805f6c0b4B7942c88111d8fB3c0597051'.toLowerCase()],
25 |
26 | [BaseAddresses.USDbC_TOKEN, '0x4c80e24119cfb836cdf0a6b53dc23f04f7e652ca'.toLowerCase()],
27 | [BaseAddresses.TETU_TOKEN, '0x0644141dd9c2c34802d28d334217bd2034206bf7'.toLowerCase()],
28 | [BaseAddresses.tUSDbC, '0x0644141dd9c2c34802d28d334217bd2034206bf7'.toLowerCase()],
29 | ]);
30 |
31 | public static async getToken(token: string, to: string, amount?: BigNumber) {
32 | const start = Date.now();
33 | const holder = TokenUtils.TOKEN_HOLDERS.get(token.toLowerCase()) as string;
34 | if (!holder) {
35 | throw new Error('Please add holder for ' + token);
36 | }
37 | const signer = await Misc.impersonate(holder);
38 | const name = await MockToken__factory.connect(token, signer).name();
39 | console.log('transfer token from biggest holder', name, token, amount?.toString());
40 |
41 | if (name.endsWith('_MOCK_TOKEN')) {
42 | const amount0 = amount || parseUnits('100');
43 | await MockToken__factory.connect(token, signer).mint(to, amount0);
44 | return amount0;
45 | }
46 |
47 | const balance = (await IERC20__factory.connect(token, signer).balanceOf(holder)).div(100);
48 | console.log('holder balance', balance.toString());
49 | if (amount) {
50 | await IERC20__factory.connect(token, signer).transfer(to, amount)
51 | } else {
52 | await IERC20__factory.connect(token, signer).transfer(to, balance)
53 | }
54 | Misc.printDuration('getToken completed', start);
55 | return balance;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/test/infrastructure/InvestFundV2Test.ts:
--------------------------------------------------------------------------------
1 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
2 | import {ethers} from "hardhat";
3 | import chai from "chai";
4 | import {TimeUtils} from "../TimeUtils";
5 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
6 | import {Misc} from "../../scripts/utils/Misc";
7 | import {ControllerV2, InvestFundV2, InvestFundV2__factory, MockToken, ProxyControlled__factory} from "../../typechain";
8 | import {parseUnits} from "ethers/lib/utils";
9 |
10 |
11 | const {expect} = chai;
12 |
13 | describe("invest fund v2 tests", function () {
14 |
15 | let snapshotBefore: string;
16 | let snapshot: string;
17 |
18 | let signer: SignerWithAddress;
19 | let signer2: SignerWithAddress;
20 |
21 | let fund: InvestFundV2;
22 | let tetu: MockToken;
23 |
24 |
25 | before(async function () {
26 | snapshotBefore = await TimeUtils.snapshot();
27 | [signer, signer2] = await ethers.getSigners();
28 |
29 | const controller = await DeployerUtils.deployController(signer);
30 | tetu = await DeployerUtils.deployMockToken(signer, 'TETU');
31 | const fundAdr = await DeployerUtils.deployProxy(signer, 'InvestFundV2');
32 | fund = InvestFundV2__factory.connect(fundAdr, signer);
33 | await fund.init(controller.address);
34 | });
35 |
36 | after(async function () {
37 | await TimeUtils.rollback(snapshotBefore);
38 | });
39 |
40 |
41 | beforeEach(async function () {
42 | snapshot = await TimeUtils.snapshot();
43 | });
44 |
45 | afterEach(async function () {
46 | await TimeUtils.rollback(snapshot);
47 | });
48 |
49 | it("withdraw test", async function () {
50 | const bal = await tetu.balanceOf(signer.address);
51 | await tetu.transfer(fund.address, parseUnits('1'));
52 | await fund.withdraw(tetu.address, parseUnits('1'))
53 | expect(await tetu.balanceOf(signer.address)).eq(bal);
54 | });
55 |
56 | it("withdraw not gov revert", async function () {
57 | await expect(fund.connect(signer2).withdraw(tetu.address, parseUnits('1'))).revertedWith('!gov');
58 | });
59 |
60 | it("deposit test", async function () {
61 | await tetu.approve(fund.address, parseUnits('1'))
62 | await fund.deposit(tetu.address, parseUnits('1'))
63 | expect(await tetu.balanceOf(fund.address)).eq(parseUnits('1'))
64 | expect((await fund.tokens())[0]).eq(tetu.address)
65 | });
66 |
67 | it("deposit zero test", async function () {
68 | await fund.deposit(tetu.address, 0)
69 | expect((await fund.tokens())[0]).eq(tetu.address)
70 | });
71 |
72 | });
73 |
--------------------------------------------------------------------------------
/test/lib/Base64Test.ts:
--------------------------------------------------------------------------------
1 | import {ethers, network} from "hardhat";
2 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
3 | import {expect} from "chai";
4 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
5 | import {
6 | Base64Test,
7 | SlotsTest,
8 | SlotsTest2,
9 | SlotsTest2__factory,
10 | SlotsTest__factory
11 | } from "../../typechain";
12 | import {TimeUtils} from "../TimeUtils";
13 |
14 | describe("Base64 Tests", function () {
15 | let snapshotBefore: string;
16 | let snapshot: string;
17 | let signer: SignerWithAddress;
18 |
19 | let helper: Base64Test;
20 |
21 | before(async function () {
22 | snapshotBefore = await TimeUtils.snapshot();
23 | [signer] = await ethers.getSigners();
24 | helper = await DeployerUtils.deployContract(signer, 'Base64Test') as Base64Test;
25 | });
26 |
27 | after(async function () {
28 | await TimeUtils.rollback(snapshotBefore);
29 | });
30 |
31 |
32 | beforeEach(async function () {
33 | snapshot = await TimeUtils.snapshot();
34 | });
35 |
36 | afterEach(async function () {
37 | await TimeUtils.rollback(snapshot);
38 | });
39 |
40 |
41 | it("empty data test", async () => {
42 | await helper.encode('0x')
43 | });
44 |
45 | })
46 |
--------------------------------------------------------------------------------
/test/lib/StringLibTest.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
3 | import {expect} from "chai";
4 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
5 | import {
6 | ControllerMinimal, ProxyControlled, ProxyControlled__factory,
7 | SlotsTest,
8 | SlotsTest2,
9 | SlotsTest2__factory,
10 | SlotsTest__factory, StringLibFacade
11 | } from "../../typechain";
12 | import {formatBytes32String} from "ethers/lib/utils";
13 | import {TimeUtils} from "../TimeUtils";
14 | import {Addresses} from "../../scripts/addresses/addresses";
15 | import {Misc} from "../../scripts/utils/Misc";
16 | import {utils} from "ethers";
17 |
18 | describe("StringLibTest", function () {
19 | let snapshotBefore: string;
20 | let snapshot: string;
21 | let signer: SignerWithAddress;
22 | let lib: StringLibFacade;
23 |
24 | before(async function () {
25 | snapshotBefore = await TimeUtils.snapshot();
26 | [signer] = await ethers.getSigners();
27 |
28 | lib = await DeployerUtils.deployContract(signer, 'StringLibFacade') as StringLibFacade;
29 | });
30 |
31 | after(async function () {
32 | await TimeUtils.rollback(snapshotBefore);
33 | });
34 |
35 |
36 | beforeEach(async function () {
37 | snapshot = await TimeUtils.snapshot();
38 | });
39 |
40 | afterEach(async function () {
41 | await TimeUtils.rollback(snapshot);
42 | });
43 |
44 |
45 | it("toString", async () => {
46 | expect(await lib.uintToString(100)).eq('100')
47 | });
48 |
49 | it("toAsciiString", async () => {
50 | expect(await lib.toAsciiString(Misc.ZERO_ADDRESS)).eq('0000000000000000000000000000000000000000')
51 | });
52 |
53 | it("char", async () => {
54 | expect(await lib.char(utils.toUtf8Bytes('z'))).eq('0xd1')
55 | });
56 |
57 |
58 | })
59 |
--------------------------------------------------------------------------------
/test/proxy/ControllableTest.ts:
--------------------------------------------------------------------------------
1 | import {ethers, network} from "hardhat";
2 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
3 | import {expect} from "chai";
4 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
5 | import {
6 | Base64Test, ControllableTest, ControllableTest__factory, ControllerMinimal,
7 | SlotsTest,
8 | SlotsTest2,
9 | SlotsTest2__factory,
10 | SlotsTest__factory
11 | } from "../../typechain";
12 | import {TimeUtils} from "../TimeUtils";
13 | import {Misc} from "../../scripts/utils/Misc";
14 |
15 | describe("Controllable Tests", function () {
16 | let snapshotBefore: string;
17 | let snapshot: string;
18 | let signer: SignerWithAddress;
19 |
20 | let helper: ControllableTest;
21 |
22 | before(async function () {
23 | snapshotBefore = await TimeUtils.snapshot();
24 | [signer] = await ethers.getSigners();
25 | helper = ControllableTest__factory.connect(await DeployerUtils.deployProxy(signer, 'ControllableTest'), signer);
26 | });
27 |
28 | after(async function () {
29 | await TimeUtils.rollback(snapshotBefore);
30 | });
31 |
32 |
33 | beforeEach(async function () {
34 | snapshot = await TimeUtils.snapshot();
35 | });
36 |
37 | afterEach(async function () {
38 | await TimeUtils.rollback(snapshot);
39 | });
40 |
41 |
42 | it("zero governance revert", async () => {
43 | const controller = await DeployerUtils.deployContract(signer, 'ControllerMinimal', Misc.ZERO_ADDRESS) as ControllerMinimal;
44 | await expect(helper.init(controller.address)).revertedWith('Zero governance');
45 | });
46 |
47 | it("zero controller revert", async () => {
48 | await expect(helper.init(Misc.ZERO_ADDRESS)).revertedWith('Zero controller');
49 | });
50 |
51 | it("revision test", async () => {
52 | await helper.increase();
53 | expect(await helper.revision()).eq(1);
54 | });
55 |
56 | it("prev impl test", async () => {
57 | await helper.increase();
58 | expect(await helper.previousImplementation()).eq(helper.address);
59 | });
60 |
61 | it("created block test", async () => {
62 | const controller = await DeployerUtils.deployContract(signer, 'ControllerMinimal', signer.address) as ControllerMinimal;
63 | await helper.init(controller.address);
64 | expect(await helper.createdBlock()).above(0);
65 | expect(await helper.created()).above(0);
66 | });
67 |
68 | it("increase rev revert test", async () => {
69 | await expect(helper.increaseRevision(Misc.ZERO_ADDRESS)).revertedWith('Increase revision forbidden');
70 | });
71 |
72 | it("read private variable", async () => {
73 | const controller = await DeployerUtils.deployContract(signer, 'ControllerMinimal', signer.address) as ControllerMinimal;
74 | await helper.init(controller.address);
75 | const bytes32Result = await helper.getSlot(1)
76 | const bytes32Expected = ethers.utils.hexZeroPad(ethers.utils.hexlify(333), 32)
77 | expect(bytes32Result).eq(bytes32Expected);
78 | });
79 | })
80 |
--------------------------------------------------------------------------------
/test/test-utils.ts:
--------------------------------------------------------------------------------
1 | import {VeTetu} from "../typechain";
2 | import {formatUnits} from "ethers/lib/utils";
3 | import chai from "chai";
4 |
5 | const {expect} = chai;
6 |
7 | export const WEEK = 60 * 60 * 24 * 7;
8 | export const LOCK_PERIOD = 60 * 60 * 24 * 90;
9 |
10 | export async function currentEpochTS(ve: VeTetu) {
11 | const blockTs = await currentTS(ve)
12 | return Math.floor(blockTs / WEEK) * WEEK;
13 | }
14 |
15 | export async function currentTS(ve: VeTetu) {
16 | return (await ve.blockTimestamp()).toNumber();
17 | }
18 |
19 | export async function checkTotalVeSupplyAtTS(ve: VeTetu, ts: number) {
20 | await ve.checkpoint();
21 |
22 | console.log('additionalTotalSupply', formatUnits(await ve.additionalTotalSupply()))
23 |
24 | const total = +formatUnits(await ve.totalSupply());
25 | console.log('total', total)
26 | const nftCount = (await ve.tokenId()).toNumber();
27 |
28 | let sum = 0;
29 | for (let i = 1; i <= nftCount; ++i) {
30 | const bal = +formatUnits(await ve.balanceOfNFT(i))
31 | console.log('bal', i, bal)
32 | sum += bal;
33 | }
34 | console.log('sum', sum)
35 | expect(sum).approximately(total, 0.0000000000001);
36 | console.log('total supply is fine')
37 | }
38 |
--------------------------------------------------------------------------------
/test/tools/ArbitragePoolSolidlyTest.ts:
--------------------------------------------------------------------------------
1 | import hre, {ethers} from "hardhat";
2 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
3 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
4 | import {ArbitragePoolSolidly, IERC20__factory, ISolidlyPair__factory, TetuVaultV2__factory} from "../../typechain";
5 | import {TimeUtils} from "../TimeUtils";
6 | import {BaseAddresses} from "../../scripts/addresses/base";
7 | import {TokenUtils} from "../TokenUtils";
8 | import {formatUnits, parseUnits} from "ethers/lib/utils";
9 | import {Misc} from "../../scripts/utils/Misc";
10 |
11 | describe("ArbitragePoolSolidlyTest", function () {
12 | let snapshotBefore: string;
13 | let snapshot: string;
14 | let signer: SignerWithAddress;
15 |
16 | let arb: ArbitragePoolSolidly;
17 |
18 | before(async function () {
19 | snapshotBefore = await TimeUtils.snapshot();
20 | [signer] = await ethers.getSigners();
21 | if (hre.network.config.chainId !== 8453) {
22 | return;
23 | }
24 | arb = await DeployerUtils.deployContract(signer, 'ArbitragePoolSolidly') as ArbitragePoolSolidly;
25 | });
26 |
27 | after(async function () {
28 | await TimeUtils.rollback(snapshotBefore);
29 | });
30 |
31 |
32 | beforeEach(async function () {
33 | snapshot = await TimeUtils.snapshot();
34 | });
35 |
36 | afterEach(async function () {
37 | await TimeUtils.rollback(snapshot);
38 | });
39 |
40 |
41 | it("arbitrage test", async () => {
42 | if (hre.network.config.chainId !== 8453) {
43 | return;
44 | }
45 |
46 | const token0 = BaseAddresses.TETU_TOKEN;
47 | const token1 = BaseAddresses.tUSDbC;
48 | const pool = BaseAddresses.TETU_tUSDbC_AERODROME_LP;
49 |
50 | await TokenUtils.getToken(BaseAddresses.USDbC_TOKEN, signer.address, parseUnits('100000', 6));
51 | await IERC20__factory.connect(BaseAddresses.USDbC_TOKEN, signer).approve(BaseAddresses.tUSDbC, Misc.MAX_UINT);
52 | // await TetuVaultV2__factory.connect(BaseAddresses.tUSDbC, signer).deposit(parseUnits('20000', 6), pool);
53 | await TetuVaultV2__factory.connect(BaseAddresses.tUSDbC, signer).deposit(parseUnits('20000', 6), arb.address);
54 | // await TokenUtils.getToken(token0, pool, parseUnits('1000000'));
55 | // await ISolidlyPair__factory.connect(pool, signer).swap(parseUnits('1', 6), 0, signer.address, '0x');
56 |
57 | const rr = await ISolidlyPair__factory.connect(pool, signer).getReserves();
58 | console.log('r0', rr[0].toString())
59 | console.log('r1', rr[1].toString())
60 |
61 | // await TokenUtils.getToken(token0, signer.address, parseUnits('1000'));
62 | // await TokenUtils.getToken(token1, signer.address, parseUnits('1000', 6));
63 |
64 | await TokenUtils.getToken(token0, arb.address, parseUnits('100000'));
65 |
66 |
67 |
68 | await arb.arbitrage(pool, '5575');
69 |
70 | console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', formatUnits(await arb.getCurrentPrice(pool), 6))
71 |
72 | await arb.arbitrage(pool, '9999');
73 |
74 | console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', formatUnits(await arb.getCurrentPrice(pool), 6))
75 |
76 | await arb.arbitrage(pool, '3000');
77 |
78 | console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', formatUnits(await arb.getCurrentPrice(pool), 6))
79 |
80 | await arb.arbitrage(pool, '15000');
81 |
82 | console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', formatUnits(await arb.getCurrentPrice(pool), 6))
83 |
84 | await arb.arbitrage(pool, '15000');
85 | });
86 |
87 |
88 | })
89 |
--------------------------------------------------------------------------------
/test/tools/BribeDistributorTest.ts:
--------------------------------------------------------------------------------
1 | // import chai from "chai";
2 | // import chaiAsPromised from "chai-as-promised";
3 | // import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
4 | // import {BribeDistribution, MockToken,} from "../../typechain";
5 | // import {TimeUtils} from "../TimeUtils";
6 | // import {ethers} from "hardhat";
7 | // import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
8 | //
9 | // const {expect} = chai;
10 | // chai.use(chaiAsPromised);
11 | //
12 | // describe("BribeDistributorTest", function () {
13 | // let snapshotBefore: string;
14 | // let snapshot: string;
15 | // let signer: SignerWithAddress;
16 | // let signer2: SignerWithAddress;
17 | //
18 | // let distr: BribeDistribution;
19 | // let token: MockToken;
20 | //
21 | //
22 | // before(async function () {
23 | // this.timeout(1200000);
24 | // snapshotBefore = await TimeUtils.snapshot();
25 | // [signer, signer2] = await ethers.getSigners();
26 | //
27 | // token = await DeployerUtils.deployMockToken(signer, 'TETU', 18);
28 | // const controller = await DeployerUtils.deployMockController(signer);
29 | // const ve = await DeployerUtils.deployVeTetu(signer, token.address, controller.address);
30 | //
31 | // const veDist = await DeployerUtils.deployVeDistributor(
32 | // signer,
33 | // controller.address,
34 | // ve.address,
35 | // token.address,
36 | // );
37 | //
38 | // distr = await DeployerUtils.deployContract(signer, "BribeDistribution", veDist.address, token.address) as BribeDistribution;
39 | // })
40 | //
41 | // after(async function () {
42 | // await TimeUtils.rollback(snapshotBefore);
43 | // });
44 | //
45 | // beforeEach(async function () {
46 | // snapshot = await TimeUtils.snapshot();
47 | // });
48 | //
49 | // afterEach(async function () {
50 | // await TimeUtils.rollback(snapshot);
51 | // });
52 | //
53 | // it("set new owner test", async () => {
54 | // await expect(distr.connect(signer2).offerOwnership(signer2.address)).revertedWith('NOT_OWNER');
55 | // await distr.offerOwnership(signer2.address)
56 | // await expect(distr.acceptOwnership()).revertedWith('NOT_OWNER');
57 | // await distr.connect(signer2).acceptOwnership()
58 | // expect(await distr.owner()).eq(signer2.address)
59 | // await expect(distr.offerOwnership(signer2.address)).revertedWith('NOT_OWNER');
60 | // })
61 | //
62 | // it("manualNotify test", async () => {
63 | // await token.approve(distr.address, 1000)
64 | // const veDist = await distr.veDist();
65 | //
66 | // await distr.manualNotify(1000, true)
67 | // expect(await token.balanceOf(veDist)).eq(500);
68 | //
69 | // await distr.manualNotify(0, false)
70 | // expect(await token.balanceOf(veDist)).eq(1000);
71 | // })
72 | //
73 | // it("autoNotify test", async () => {
74 | // const bal = await token.balanceOf(signer.address);
75 | // await token.approve(distr.address, bal)
76 | // const veDist = await distr.veDist();
77 | //
78 | // await distr.autoNotify()
79 | // expect(await token.balanceOf(veDist)).eq(bal.div(2));
80 | //
81 | // await distr.autoNotify()
82 | // expect(await token.balanceOf(veDist)).eq(bal);
83 | // })
84 | // })
85 |
--------------------------------------------------------------------------------
/test/tools/DepositHelperTests.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
3 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
4 | import {DepositHelperPolygon, IERC20__factory, MockToken, MockVault, VeTetu} from "../../typechain";
5 | import {TimeUtils} from "../TimeUtils";
6 | import {expect} from "chai";
7 | import {Misc} from "../../scripts/utils/Misc";
8 |
9 | describe("Deposit helper Tests", function () {
10 | let snapshotBefore: string;
11 | let snapshot: string;
12 | let signer: SignerWithAddress;
13 | let signer2: SignerWithAddress;
14 | let strategy: SignerWithAddress;
15 |
16 |
17 | let token: MockToken;
18 | let token2: MockToken;
19 | let vault: MockVault;
20 | let helper: DepositHelperPolygon;
21 | let ve: VeTetu;
22 |
23 | before(async function () {
24 | snapshotBefore = await TimeUtils.snapshot();
25 | [signer, strategy, signer2] = await ethers.getSigners();
26 |
27 | const controller = await DeployerUtils.deployMockController(signer);
28 | token = await DeployerUtils.deployMockToken(signer);
29 | token2 = await DeployerUtils.deployMockToken(signer);
30 | vault = await DeployerUtils.deployMockVault(signer, controller.address, token.address, 'V', strategy.address, 1);
31 | helper = await DeployerUtils.deployContract(signer, 'DepositHelperPolygon', token.address) as DepositHelperPolygon;
32 |
33 | ve = await DeployerUtils.deployVeTetu(signer, token.address, controller.address);
34 |
35 | await token.connect(strategy).approve(vault.address, 99999999999);
36 |
37 | await token.approve(vault.address, 10000);
38 | await vault.deposit(10000, signer.address);
39 | });
40 |
41 | after(async function () {
42 | await TimeUtils.rollback(snapshotBefore);
43 | });
44 |
45 |
46 | beforeEach(async function () {
47 | snapshot = await TimeUtils.snapshot();
48 | });
49 |
50 | afterEach(async function () {
51 | await TimeUtils.rollback(snapshot);
52 | });
53 |
54 |
55 | it("test deposit", async () => {
56 | await token.approve(helper.address, 100)
57 | await helper.deposit(vault.address, token.address, 100, 99)
58 | expect(await vault.balanceOf(signer.address)).eq(8999);
59 |
60 | await token.approve(helper.address, 100)
61 | await expect(helper.deposit(vault.address, token.address, 100, 101)).to.be.revertedWith('SLIPPAGE')
62 |
63 | await token.approve(helper.address, 100)
64 | await helper.deposit(vault.address, token.address, 100, 99)
65 | expect(await vault.balanceOf(signer.address)).eq(9098);
66 |
67 | await IERC20__factory.connect(vault.address, signer).approve(helper.address, 198)
68 | await expect(helper.withdraw(vault.address, 198, 199)).to.be.revertedWith('SLIPPAGE')
69 |
70 | const balanceBefore = await token.balanceOf(signer.address)
71 | await helper.withdraw(vault.address, 198, 198)
72 | expect((await token.balanceOf(signer.address)).sub(balanceBefore)).eq(198);
73 | });
74 |
75 | it("test create lock", async () => {
76 | await token.approve(helper.address, 1000)
77 | await helper.createLock(ve.address, token.address, 1000, 60 * 60 * 24 * 30);
78 | expect((await ve.lockedAmounts(1, token.address))).eq(1000);
79 | });
80 |
81 | it("test increase amount", async () => {
82 | await token.approve(helper.address, 1000)
83 | await helper.createLock(ve.address, token.address, 1000, 60 * 60 * 24 * 30);
84 | await token.approve(helper.address, 1000)
85 | await helper.increaseAmount(ve.address, token.address, 1, 1000);
86 | expect((await ve.lockedAmounts(1, token.address))).eq(2000);
87 | });
88 |
89 | })
90 |
--------------------------------------------------------------------------------
/test/tools/PerfFeeTreasuryTest.ts:
--------------------------------------------------------------------------------
1 | import chai from "chai";
2 | import chaiAsPromised from "chai-as-promised";
3 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
4 | import {PerfFeeTreasury,} from "../../typechain";
5 | import {TimeUtils} from "../TimeUtils";
6 | import {ethers} from "hardhat";
7 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
8 |
9 | const {expect} = chai;
10 | chai.use(chaiAsPromised);
11 |
12 | describe("PerfFeeTreasuryTest", function () {
13 | let snapshotBefore: string;
14 | let snapshot: string;
15 | let signer: SignerWithAddress;
16 | let signer2: SignerWithAddress;
17 |
18 | let treasury: PerfFeeTreasury;
19 |
20 |
21 | before(async function () {
22 | this.timeout(1200000);
23 | snapshotBefore = await TimeUtils.snapshot();
24 | [signer, signer2] = await ethers.getSigners();
25 |
26 | treasury = await DeployerUtils.deployContract(signer, "PerfFeeTreasury", signer.address) as PerfFeeTreasury;
27 | })
28 |
29 | after(async function () {
30 | await TimeUtils.rollback(snapshotBefore);
31 | });
32 |
33 | beforeEach(async function () {
34 | snapshot = await TimeUtils.snapshot();
35 | });
36 |
37 | afterEach(async function () {
38 | await TimeUtils.rollback(snapshot);
39 | });
40 |
41 | it("set new gov", async () => {
42 | await expect(treasury.connect(signer2).offerOwnership(signer2.address)).revertedWith('NOT_GOV');
43 | await treasury.offerOwnership(signer2.address)
44 | await expect(treasury.acceptOwnership()).revertedWith('NOT_GOV');
45 | await treasury.connect(signer2).acceptOwnership()
46 | expect(await treasury.governance()).eq(signer2.address)
47 | await expect(treasury.offerOwnership(signer2.address)).revertedWith('NOT_GOV');
48 | })
49 |
50 | it("claim", async () => {
51 | const token = await DeployerUtils.deployMockToken(signer);
52 | const token2 = await DeployerUtils.deployMockToken(signer);
53 |
54 | await token.transfer(treasury.address, 1000)
55 | await token2.transfer(treasury.address, 500)
56 |
57 | expect(await token.balanceOf(treasury.address)).eq(1000);
58 | expect(await token2.balanceOf(treasury.address)).eq(500);
59 |
60 | await expect(treasury.connect(signer2).claim([token.address, token2.address])).revertedWith('NOT_GOV');
61 | await treasury.claim([token.address, token2.address]);
62 |
63 | expect(await token.balanceOf(treasury.address)).eq(0);
64 | expect(await token2.balanceOf(treasury.address)).eq(0);
65 | })
66 | })
67 |
--------------------------------------------------------------------------------
/test/tools/TetuERC165Test.ts:
--------------------------------------------------------------------------------
1 | import {ethers} from "hardhat";
2 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
3 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
4 | import {InterfaceIds, MockToken, TetuERC165Test} from "../../typechain";
5 | import {TimeUtils} from "../TimeUtils";
6 | import {expect} from "chai";
7 | import {constants} from "ethers";
8 |
9 | describe("TetuERC165Test", function () {
10 | let snapshotBefore: string;
11 | let snapshot: string;
12 | let signer: SignerWithAddress;
13 |
14 | let test: TetuERC165Test;
15 | let interfaceIds: InterfaceIds;
16 | let token: MockToken;
17 |
18 | before(async function () {
19 | snapshotBefore = await TimeUtils.snapshot();
20 | [signer] = await ethers.getSigners();
21 |
22 | interfaceIds = await DeployerUtils.deployContract(signer, 'InterfaceIds') as InterfaceIds;
23 | test = await DeployerUtils.deployContract(signer, 'TetuERC165Test') as TetuERC165Test;
24 | token = await DeployerUtils.deployMockToken(signer, 'TOKEN', 18);
25 |
26 | });
27 |
28 | after(async function () {
29 | await TimeUtils.rollback(snapshotBefore);
30 | });
31 |
32 |
33 | beforeEach(async function () {
34 | snapshot = await TimeUtils.snapshot();
35 | });
36 |
37 | afterEach(async function () {
38 | await TimeUtils.rollback(snapshot);
39 | });
40 |
41 |
42 | it("is interface supported", async () => {
43 | await expect(test.isInterfaceSupported(constants.AddressZero, '0x00000000')).revertedWith('Zero address')
44 | expect(await test.isInterfaceSupported(signer.address, '0x00000000')).eq(false);
45 | expect(await test.isInterfaceSupported(test.address, '0x00000000')).eq(false);
46 | expect(await test.isInterfaceSupported(test.address, await interfaceIds.I_TETU_ERC165())).eq(true);
47 | expect(await test.isInterfaceSupported(token.address, await interfaceIds.I_CONTROLLER())).eq(false);
48 | });
49 |
50 | it("require interface", async () => {
51 | const I_TETU_ERC165 = await interfaceIds.I_TETU_ERC165();
52 | const I_CONTROLLER = await interfaceIds.I_CONTROLLER();
53 | expect(await test.requireInterface(test.address, I_TETU_ERC165)).deep.eq([]); // executed without return values
54 | expect(test.requireInterface(test.address, '0x00000000')).revertedWith('Interface is not supported');
55 | expect(test.requireInterface(test.address, I_CONTROLLER)).revertedWith('Interface is not supported');
56 | });
57 |
58 | it("is ERC20", async () => {
59 | await expect(test.isERC20(constants.AddressZero)).revertedWith('Zero address');
60 | expect(await test.isERC20(signer.address)).eq(false);
61 | expect(await test.isERC20(test.address)).eq(false);
62 | expect(await test.isERC20(token.address)).eq(true);
63 | });
64 |
65 |
66 | it("require ERC20", async () => {
67 | expect(await test.requireERC20(token.address)).deep.eq([]); // executed without return values
68 | expect(test.requireERC20(test.address)).revertedWith('Not ERC20');
69 | expect(test.requireERC20(ethers.constants.AddressZero)).revertedWith('Not ERC20');
70 | });
71 |
72 |
73 | })
74 |
--------------------------------------------------------------------------------
/test/vault/VaultFactoryPolygonTests.ts:
--------------------------------------------------------------------------------
1 | import chai from "chai";
2 | import chaiAsPromised from "chai-as-promised";
3 | import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
4 | import hre, {ethers} from "hardhat";
5 | import {TimeUtils} from "../TimeUtils";
6 | import {DeployerUtils} from "../../scripts/utils/DeployerUtils";
7 | import {VaultFactory, VaultFactory__factory} from "../../typechain";
8 | import {Misc} from "../../scripts/utils/Misc";
9 | import {CoreAddresses} from "../../scripts/models/CoreAddresses";
10 | import {Addresses} from "../../scripts/addresses/addresses";
11 | import {PolygonAddresses} from "../../scripts/addresses/polygon";
12 |
13 |
14 | const {expect} = chai;
15 | chai.use(chaiAsPromised);
16 |
17 | describe("Vault factory tests", function () {
18 | let snapshotBefore: string;
19 | let snapshot: string;
20 | let signer: SignerWithAddress;
21 | let gov: SignerWithAddress;
22 | let core: CoreAddresses;
23 | let factory: VaultFactory;
24 |
25 |
26 | before(async function () {
27 | [signer] = await ethers.getSigners()
28 | snapshotBefore = await TimeUtils.snapshot();
29 | if (hre.network.config.chainId !== 137) {
30 | return;
31 | }
32 |
33 | gov = await Misc.impersonate(PolygonAddresses.GOVERNANCE);
34 |
35 | core = Addresses.getCore();
36 | factory = VaultFactory__factory.connect(core.vaultFactory, gov);
37 | });
38 |
39 | after(async function () {
40 | await TimeUtils.rollback(snapshotBefore);
41 | });
42 |
43 | beforeEach(async function () {
44 | snapshot = await TimeUtils.snapshot();
45 | });
46 |
47 | afterEach(async function () {
48 | await TimeUtils.rollback(snapshot);
49 | });
50 |
51 | it("set vault logic", async () => {
52 | if (hre.network.config.chainId !== 137) {
53 | return;
54 | }
55 | console.log('factory', factory.address);
56 | const vaultLogic = await DeployerUtils.deployContract(signer, 'TetuVaultV2');
57 | await factory.setVaultImpl(vaultLogic.address);
58 | expect(await factory.vaultImpl()).to.be.eq(vaultLogic.address);
59 | });
60 |
61 | it("set splitter logic", async () => {
62 | if (hre.network.config.chainId !== 137) {
63 | return;
64 | }
65 | const splitter = await DeployerUtils.deployContract(signer, 'StrategySplitterV2');
66 | await factory.setSplitterImpl(splitter.address);
67 | expect(await factory.splitterImpl()).to.be.eq(splitter.address);
68 | });
69 |
70 |
71 | });
72 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "sourceMap": true,
4 | "target": "es2019",
5 | "module": "commonjs",
6 | "strict": true,
7 | "esModuleInterop": true,
8 | "outDir": "dist",
9 | "resolveJsonModule": true,
10 | "declaration": true
11 | },
12 | "include": [
13 | "./scripts",
14 | "./test",
15 | "./typechain",
16 | "./tmp"
17 | ],
18 | "exclude": ["node_modules"],
19 | "files": [
20 | "./hardhat.config.ts",
21 | "./scripts/addresses/addresses.ts"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "tslint:latest"
4 | ],
5 | "rules": {
6 | "ban-ts-ignore": true,
7 | "no-any": true,
8 | "no-non-null-assertion": true,
9 | "object-literal-sort-keys": false,
10 | "promise-function-async": true,
11 | "await-promise": false,
12 | "no-submodule-imports": false,
13 | "interface-name": [true, "always-prefix"],
14 | "max-classes-per-file": [true, 1],
15 | "no-empty": false,
16 | "no-console": false,
17 | "only-arrow-functions": false,
18 | "variable-name": [
19 | true,
20 | "check-format",
21 | "allow-leading-underscore",
22 | "allow-pascal-case"
23 | ],
24 | "ordered-imports": [
25 | false
26 | ],
27 | "no-floating-promises": true,
28 | "prefer-conditional-expression": false,
29 | "no-implicit-dependencies": false,
30 | "indent": [
31 | true,
32 | "spaces",
33 | 2
34 | ],
35 | "whitespace" : [false]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/veTETU.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------