├── launchpad ├── README.md ├── .gitignore ├── .env.example ├── contracts │ └── interfaces │ │ ├── IScoreCalculator.sol │ │ ├── IWMNT.sol │ │ ├── IERC20.sol │ │ └── IInsurancePool.sol ├── tsconfig.json ├── deployments │ ├── mantleTestnet.json │ └── mantleSepoliaTestnet.json ├── package.json └── scripts │ ├── add_staking_token.ts │ └── add_staking_token copy.ts ├── multicall3 ├── README.md ├── deployments │ ├── mantleMainnet.json │ └── mantleSepoliaTestnet.json ├── .env.example ├── .gitignore ├── tsconfig.json ├── scripts │ ├── verify.ts │ └── deploy.ts ├── common │ └── utils.ts └── package.json ├── .gitignore ├── farmbooster ├── README.md ├── .env.example ├── .gitignore ├── tsconfig.json ├── contracts │ ├── interfaces │ │ ├── IAgniPool.sol │ │ └── IMasterChefV3.sol │ └── libraries │ │ └── IterateMapping.sol ├── scripts │ ├── deploy.ts │ └── verify.ts ├── package.json └── hardhat.config.ts ├── lm-pool ├── deployments │ ├── mantleTestnet.json │ └── mantleSepoliaTestnet.json ├── .env.example ├── .gitignore ├── contracts │ ├── interfaces │ │ ├── IAgniLmPool.sol │ │ └── IMasterChefV3.sol │ └── AgniLmPoolDeployer.sol ├── tsconfig.json ├── README.md ├── scripts │ ├── verify.ts │ └── deploy.ts ├── package.json └── hardhat.config.ts ├── core ├── .env.example ├── .gitignore ├── contracts │ ├── interfaces │ │ ├── IAgniLmPool.sol │ │ ├── IAgniPool.sol │ │ ├── callback │ │ │ ├── IAgniMintCallback.sol │ │ │ ├── IAgniFlashCallback.sol │ │ │ └── IAgniSwapCallback.sol │ │ ├── pool │ │ │ ├── IAgniPoolOwnerActions.sol │ │ │ └── IAgniPoolImmutables.sol │ │ └── IAgniPoolDeployer.sol │ ├── libraries │ │ ├── FixedPoint128.sol │ │ ├── FixedPoint96.sol │ │ ├── LiquidityMath.sol │ │ ├── UnsafeMath.sol │ │ ├── TransferHelper.sol │ │ ├── SafeCast.sol │ │ └── LowGasSafeMath.sol │ ├── test │ │ ├── OutputCodeHash.sol │ │ ├── UnsafeMathEchidnaTest.sol │ │ ├── LiquidityMathTest.sol │ │ ├── FullMathTest.sol │ │ ├── BitMathEchidnaTest.sol │ │ ├── MockTimeAgniPool.sol │ │ ├── BitMathTest.sol │ │ ├── TickMathEchidnaTest.sol │ │ ├── TickEchidnaTest.sol │ │ ├── MockTimeAgniPoolDeployer.sol │ │ ├── SwapMathTest.sol │ │ ├── LowGasSafeMathEchidnaTest.sol │ │ ├── TickMathTest.sol │ │ ├── TestAgniSwapPay.sol │ │ ├── TickBitmapTest.sol │ │ ├── AgniPoolSwapTest.sol │ │ ├── TickBitmapEchidnaTest.sol │ │ ├── FullMathEchidnaTest.sol │ │ └── SwapMathEchidnaTest.sol │ └── AgniPoolDeployer.sol ├── tsconfig.json ├── deployments │ ├── mantleMainnet.json │ ├── mantleTestnet.json │ └── mantleSepoliaTestnet.json ├── README.md ├── scripts │ ├── verify.ts │ ├── pool_address.ts │ └── deploy.ts └── package.json ├── periphery ├── .env.example ├── contracts │ ├── lens │ │ ├── README.md │ │ ├── AgniInterfaceMulticall.sol │ │ └── TickLens.sol │ ├── interfaces │ │ ├── IImmutableState.sol │ │ ├── ISmartRouter.sol │ │ ├── IPeripheryImmutableState.sol │ │ ├── IERC20Metadata.sol │ │ ├── IMulticall.sol │ │ ├── external │ │ │ ├── IWMNT.sol │ │ │ ├── IERC1271.sol │ │ │ └── IERC20PermitAllowed.sol │ │ ├── INonfungibleTokenPositionDescriptor.sol │ │ ├── ITickLens.sol │ │ ├── IPoolInitializer.sol │ │ ├── IPeripheryPaymentsWithFee.sol │ │ ├── IPeripheryPayments.sol │ │ └── IERC721Permit.sol │ ├── test │ │ ├── SelfPermitTest.sol │ │ ├── TestERC20.sol │ │ ├── PeripheryImmutableStateTest.sol │ │ ├── TestERC20Metadata.sol │ │ ├── TestCallbackValidation.sol │ │ ├── Base64Test.sol │ │ ├── MockTimeSwapRouter.sol │ │ ├── TickLensTest.sol │ │ ├── PoolTicksCounterTest.sol │ │ ├── NonfungiblePositionManagerPositionsGasTest.sol │ │ ├── MockTimeNonfungiblePositionManager.sol │ │ ├── TestMulticall.sol │ │ ├── TestERC20PermitAllowed.sol │ │ ├── TestPositionNFTOwner.sol │ │ ├── PoolAddressTest.sol │ │ ├── PathTest.sol │ │ ├── MockObservable.sol │ │ ├── PositionValueTest.sol │ │ └── WMNT.sol │ ├── base │ │ ├── PeripheryValidation.sol │ │ ├── BlockTimestamp.sol │ │ ├── ImmutableState.sol │ │ ├── PeripheryImmutableState.sol │ │ ├── Multicall.sol │ │ ├── PoolInitializer.sol │ │ ├── PeripheryPaymentsWithFee.sol │ │ └── SelfPermit.sol │ ├── libraries │ │ ├── TokenRatioSortOrder.sol │ │ ├── ChainId.sol │ │ ├── PositionKey.sol │ │ ├── Constants.sol │ │ ├── HexStrings.sol │ │ ├── CallbackValidation.sol │ │ └── PoolAddress.sol │ ├── SmartRouter.sol │ └── NonfungibleTokenPositionDescriptorOffChain.sol ├── .gitignore ├── test │ └── shared │ │ ├── expandTo18Decimals.ts │ │ ├── expect.ts │ │ ├── base64.ts │ │ ├── extractJSONFromURI.ts │ │ ├── constants.ts │ │ ├── tokenSort.ts │ │ ├── poolAtAddress.ts │ │ ├── ticks.ts │ │ ├── encodePriceSqrt.ts │ │ ├── snapshotGasCost.ts │ │ ├── formatSqrtRatioX96.ts │ │ ├── computePoolAddress.ts │ │ ├── formatSqrtRatioX96.spec.ts │ │ ├── getPermitNFTSignature.ts │ │ ├── permit.ts │ │ └── path.ts ├── tsconfig.json ├── deployments │ ├── mantleTestnet.json │ ├── mantleMainnet.json │ └── mantleSepoliaTestnet.json ├── scripts │ ├── pool_address.ts │ ├── quoteV2.ts │ ├── deploy_slf.ts │ ├── swap.ts │ └── init_pool.ts └── README.md ├── masterchef ├── .env.example ├── .gitignore ├── deployments │ ├── mantleTestnet.json │ └── mantleSepoliaTestnet.json ├── contracts │ ├── interfaces │ │ ├── IReceiver.sol │ │ ├── ILMPoolDeployer.sol │ │ ├── IWMNT.sol │ │ ├── ILMPool.sol │ │ ├── IFarmBooster.sol │ │ ├── IIncentivePool.sol │ │ ├── INonfungiblePositionManagerStruct.sol │ │ ├── IAgniPool.sol │ │ └── IMasterChefV3.sol │ ├── utils │ │ └── Multicall.sol │ └── libraries │ │ └── SafeCast.sol ├── tsconfig.json ├── README.md ├── scripts │ ├── deposit_wmnt.ts │ ├── upkeep.ts │ ├── add_pool.ts │ └── verify.ts └── package.json ├── v2-protocol ├── README.md ├── .gitignore ├── tsconfig.json ├── contracts │ ├── interfaces │ │ ├── IAgniCallee.sol │ │ ├── IWETH.sol │ │ ├── IAgniMigrator.sol │ │ ├── IAgniRouterV2.sol │ │ ├── IAgniFactory.sol │ │ ├── IERC20.sol │ │ ├── IAgniERC20.sol │ │ └── IAgniPair.sol │ ├── libraries │ │ ├── SafeMath.sol │ │ ├── UQ112x112.sol │ │ └── Math.sol │ └── AgniFactory.sol ├── deployments │ ├── mantleMainnet.json │ └── mantleSepoliaTestnet.json ├── package.json └── scripts │ └── verify.ts ├── package.json ├── README.md ├── common └── utils.ts ├── deployments ├── mantleSepoliaTestnet.json ├── mantleMainnet.json └── mantleTestnet.json └── deploy.mjs /launchpad/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /multicall3/README.md: -------------------------------------------------------------------------------- 1 | # Agni multicall3 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | */yarn.lock -------------------------------------------------------------------------------- /farmbooster/README.md: -------------------------------------------------------------------------------- 1 | # Agni farm blooster 2 | -------------------------------------------------------------------------------- /multicall3/deployments/mantleMainnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Multicall3": "0x05f3105fc9FC531712b2570f1C6E11dD4bCf7B3c" 3 | } -------------------------------------------------------------------------------- /lm-pool/deployments/mantleTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniLmPoolDeployer": "0x8e8a453Bc0d968bBb284766aa4fE018a367E3106" 3 | } -------------------------------------------------------------------------------- /core/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | MANTLE_API_KEY=XXXXXXXXXX 3 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz -------------------------------------------------------------------------------- /multicall3/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Multicall3": "0x521751C88EafdCAEd9cAbb4dB35a1400D6933428" 3 | } -------------------------------------------------------------------------------- /lm-pool/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | MANTLESCAN_API_KEY=XXXXXXXXXX 3 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz -------------------------------------------------------------------------------- /lm-pool/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniLmPoolDeployer": "0x5E804Ce9B7F6e85A6e70C8265F72A9c9a7D38c93" 3 | } -------------------------------------------------------------------------------- /periphery/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | MANTLESCAN_API_KEY=XXXXXXXXXX 3 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz -------------------------------------------------------------------------------- /masterchef/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | MANTLESCAN_API_KEY=XXXXXXXXXX 3 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz -------------------------------------------------------------------------------- /v2-protocol/README.md: -------------------------------------------------------------------------------- 1 | # Exchange Protocol 2 | 3 | ## Description 4 | 5 | This repo includes core and peripheral contracts from Uniswap V2. 6 | -------------------------------------------------------------------------------- /farmbooster/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | MANTLESCAN_API_KEY=XXXXXXXXXX 3 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz 4 | NETWORK=mantleMainnet -------------------------------------------------------------------------------- /multicall3/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | MANTLESCAN_API_KEY=XXXXXXXXXX 3 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz 4 | NETWORK=mantleMainnet -------------------------------------------------------------------------------- /periphery/contracts/lens/README.md: -------------------------------------------------------------------------------- 1 | # lens 2 | 3 | These contracts are not designed to be called on-chain. They simplify 4 | fetching on-chain data from off-chain. 5 | -------------------------------------------------------------------------------- /core/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | 12 | -------------------------------------------------------------------------------- /lm-pool/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | 12 | -------------------------------------------------------------------------------- /masterchef/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | 12 | -------------------------------------------------------------------------------- /multicall3/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | 12 | -------------------------------------------------------------------------------- /v2-protocol/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | data -------------------------------------------------------------------------------- /farmbooster/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | 12 | -------------------------------------------------------------------------------- /launchpad/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | .openzeppelin -------------------------------------------------------------------------------- /periphery/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | 8 | # Hardhat files 9 | cache 10 | artifacts 11 | .openzeppelin -------------------------------------------------------------------------------- /masterchef/deployments/mantleTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "MasterChef": "0x0BC31D78e06ef928658e0B6AB50460552f3D91c4", 3 | "MasterChefV3Receiver": "0x882a2c07Bf04DEcCA36Be060B07d8BC0EE50D2Ff" 4 | } -------------------------------------------------------------------------------- /launchpad/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=XXXXXX 2 | ADDRSS=XXXXXX 3 | 4 | KEEPER_PRIVATE_KEY=XXXXXX 5 | KEEPER_ADDRESS=XXXXXX 6 | 7 | MANTLESCAN_API_KEY=XXXXXXXXXX 8 | MANTLE_TESTNET_URL=https://rpc.testnet.mantle.xyz -------------------------------------------------------------------------------- /periphery/test/shared/expandTo18Decimals.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from 'ethers' 2 | 3 | export function expandTo18Decimals(n: number): BigNumber { 4 | return BigNumber.from(n).mul(BigNumber.from(10).pow(18)) 5 | } 6 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/IReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | interface IReceiver { 5 | function upkeep(uint256 amount, uint256 duration, bool withUpdate) external; 6 | } 7 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IImmutableState.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | interface IImmutableState { 5 | function factoryV2() external view returns (address); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /launchpad/contracts/interfaces/IScoreCalculator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.7.6; 3 | 4 | interface IScoreCalculator { 5 | function calculate(address token, uint256 tokenIdOrAmount) external view returns (uint256 score); 6 | } -------------------------------------------------------------------------------- /periphery/test/shared/expect.ts: -------------------------------------------------------------------------------- 1 | import { expect, use } from 'chai' 2 | import { solidity } from 'ethereum-waffle' 3 | import { jestSnapshotPlugin } from 'mocha-chai-jest-snapshot' 4 | 5 | use(solidity) 6 | use(jestSnapshotPlugin()) 7 | 8 | export { expect } 9 | -------------------------------------------------------------------------------- /periphery/contracts/test/SelfPermitTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../base/SelfPermit.sol'; 5 | 6 | /// @dev Same as SelfPermit but not abstract 7 | contract SelfPermitTest is SelfPermit { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /periphery/test/shared/base64.ts: -------------------------------------------------------------------------------- 1 | export function base64Encode(str: string): string { 2 | return Buffer.from(str, 'utf8').toString('base64') 3 | } 4 | 5 | export function base64Decode(str: string): string { 6 | return Buffer.from(str, 'base64').toString('utf8') 7 | } 8 | -------------------------------------------------------------------------------- /core/contracts/interfaces/IAgniLmPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | interface IAgniLmPool { 5 | function accumulateReward(uint32 currTimestamp) external; 6 | 7 | function crossLmTick(int24 tick, bool zeroForOne) external; 8 | } 9 | -------------------------------------------------------------------------------- /lm-pool/contracts/interfaces/IAgniLmPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | interface IAgniLmPool { 5 | function accumulateReward(uint32 currTimestamp) external; 6 | 7 | function crossLmTick(int24 tick, bool zeroForOne) external; 8 | } 9 | -------------------------------------------------------------------------------- /core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/ILMPoolDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | import "./IAgniPool.sol"; 5 | import "./ILMPool.sol"; 6 | 7 | interface ILMPoolDeployer { 8 | function deploy(IAgniPool pool) external returns (ILMPool lmPool); 9 | } 10 | -------------------------------------------------------------------------------- /farmbooster/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /launchpad/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lm-pool/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /masterchef/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /multicall3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /periphery/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /v2-protocol/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "agni-contracts", 3 | "devDependencies": { 4 | "zx": "^7.2.0", 5 | "@typechain/hardhat": "^6.1.5", 6 | "solidity-docgen": "^0.6.0-beta.35", 7 | "find-config": "^1.0.0", 8 | "dotenv": "^16.0.3" 9 | }, 10 | "volta": { 11 | "node": "16.19.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IAgniCallee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IAgniCallee { 5 | function agniCall( 6 | address sender, 7 | uint256 amount0, 8 | uint256 amount1, 9 | bytes calldata data 10 | ) external; 11 | } 12 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IWETH { 5 | function deposit() external payable; 6 | 7 | function transfer(address to, uint256 value) external returns (bool); 8 | 9 | function withdraw(uint256) external; 10 | } 11 | -------------------------------------------------------------------------------- /core/deployments/mantleMainnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniPoolDeployer": "0xe9827B4EBeB9AE41FC57efDdDd79EDddC2EA4d03", 3 | "AgniFactory": "0x25780dc8Fc3cfBD75F33bFDAB65e969b603b2035", 4 | "InitCodeHashAddress": "0x5cfa0f1c4067C90a50B973e5F98CD265de5Df724", 5 | "InitCodeHash": "0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a" 6 | } -------------------------------------------------------------------------------- /core/deployments/mantleTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniPoolDeployer": "0x0B7e80F0e664ae80bbE0c56f7908ef14f5898b1d", 3 | "AgniFactory": "0x503Ca2ad7C9C70F4157d14CF94D3ef5Fa96D7032", 4 | "InitCodeHashAddress": "0xECeFAd547Dd6E5556065dF7797D9fC892B5EA864", 5 | "InitCodeHash": "0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a" 6 | } -------------------------------------------------------------------------------- /periphery/test/shared/extractJSONFromURI.ts: -------------------------------------------------------------------------------- 1 | export function extractJSONFromURI(uri: string): { name: string; description: string; image: string } { 2 | const encodedJSON = uri.substr('data:application/json;base64,'.length) 3 | const decodedJSON = Buffer.from(encodedJSON, 'base64').toString('utf8') 4 | return JSON.parse(decodedJSON) 5 | } 6 | -------------------------------------------------------------------------------- /core/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniPoolDeployer": "0x6C53C6cC7c10B389c5680458Fc0C4079f3F012b4", 3 | "AgniFactory": "0xA9AcD50B042A72c33d05fDcC8ad209d3aD361762", 4 | "InitCodeHashAddress": "0xa18655b73FDC38665CFB9e09A5a0a10C14e68EC5", 5 | "InitCodeHash": "0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a" 6 | } -------------------------------------------------------------------------------- /lm-pool/contracts/interfaces/IMasterChefV3.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | interface IMasterChefV3 { 5 | function nonfungiblePositionManager() external view returns (address); 6 | 7 | function getLatestPeriodInfo(address _pool) external view returns (uint256 cakePerSecond, uint256 endTime); 8 | } 9 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IAgniMigrator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IAgniMigrator { 5 | function migrate( 6 | address token, 7 | uint256 amountTokenMin, 8 | uint256 amountETHMin, 9 | address to, 10 | uint256 deadline 11 | ) external; 12 | } 13 | -------------------------------------------------------------------------------- /core/contracts/libraries/FixedPoint128.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.4.0; 3 | 4 | /// @title FixedPoint128 5 | /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) 6 | library FixedPoint128 { 7 | uint256 internal constant Q128 = 0x100000000000000000000000000000000; 8 | } 9 | -------------------------------------------------------------------------------- /periphery/contracts/test/TestERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '@openzeppelin/contracts/drafts/ERC20Permit.sol'; 5 | 6 | contract TestERC20 is ERC20Permit { 7 | constructor(uint256 amountToMint) ERC20('Test ERC20', 'TEST') ERC20Permit('Test ERC20') { 8 | _mint(msg.sender, amountToMint); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /periphery/contracts/test/PeripheryImmutableStateTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '../base/PeripheryImmutableState.sol'; 5 | 6 | contract PeripheryImmutableStateTest is PeripheryImmutableState { 7 | constructor(address _deployer, address _factory, address _WMNT) PeripheryImmutableState(_deployer, _factory, _WMNT) {} 8 | } 9 | -------------------------------------------------------------------------------- /periphery/contracts/base/PeripheryValidation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import './BlockTimestamp.sol'; 5 | 6 | abstract contract PeripheryValidation is BlockTimestamp { 7 | modifier checkDeadline(uint256 deadline) { 8 | require(_blockTimestamp() <= deadline, 'Transaction too old'); 9 | _; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/contracts/test/OutputCodeHash.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | import "../AgniPool.sol"; 6 | 7 | contract OutputCodeHash { 8 | function getInitCodeHash() public pure returns(bytes32){ 9 | bytes memory bytecode = type(AgniPool).creationCode; 10 | return keccak256(abi.encodePacked(bytecode)); 11 | } 12 | } -------------------------------------------------------------------------------- /periphery/test/shared/constants.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from 'ethers' 2 | 3 | export const MaxUint128 = BigNumber.from(2).pow(128).sub(1) 4 | 5 | export enum FeeAmount { 6 | LOW = 500, 7 | MEDIUM = 2500, 8 | HIGH = 10000, 9 | } 10 | 11 | export const TICK_SPACINGS: { [amount in FeeAmount]: number } = { 12 | [FeeAmount.LOW]: 10, 13 | [FeeAmount.MEDIUM]: 50, 14 | [FeeAmount.HIGH]: 200, 15 | } 16 | -------------------------------------------------------------------------------- /periphery/test/shared/tokenSort.ts: -------------------------------------------------------------------------------- 1 | export function compareToken(a: { address: string }, b: { address: string }): -1 | 1 { 2 | return a.address.toLowerCase() < b.address.toLowerCase() ? -1 : 1 3 | } 4 | 5 | export function sortedTokens( 6 | a: { address: string }, 7 | b: { address: string } 8 | ): [typeof a, typeof b] | [typeof b, typeof a] { 9 | return compareToken(a, b) < 0 ? [a, b] : [b, a] 10 | } 11 | -------------------------------------------------------------------------------- /launchpad/contracts/interfaces/IWMNT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.7.6; 3 | 4 | import "./IERC20.sol"; 5 | 6 | /// @title Interface for WMNT 7 | interface IWMNT is IERC20 { 8 | /// @notice Deposit ether to get wrapped ether 9 | function deposit() external payable; 10 | 11 | /// @notice Withdraw wrapped ether to get ether 12 | function withdraw(uint256) external; 13 | } 14 | -------------------------------------------------------------------------------- /lm-pool/README.md: -------------------------------------------------------------------------------- 1 | # Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat help 9 | npx hardhat test 10 | REPORT_GAS=true npx hardhat test 11 | npx hardhat node 12 | npx hardhat run scripts/deploy.ts 13 | ``` 14 | -------------------------------------------------------------------------------- /masterchef/README.md: -------------------------------------------------------------------------------- 1 | # Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat help 9 | npx hardhat test 10 | REPORT_GAS=true npx hardhat test 11 | npx hardhat node 12 | npx hardhat run scripts/deploy.ts 13 | ``` 14 | -------------------------------------------------------------------------------- /periphery/test/shared/poolAtAddress.ts: -------------------------------------------------------------------------------- 1 | import { abi as POOL_ABI } from '@pancakeswap/v3-core/artifacts/contracts/PancakeV3Pool.sol/PancakeV3Pool.json' 2 | import { Contract, Wallet } from 'ethers' 3 | import { IPancakeV3Pool } from '../../typechain-types' 4 | 5 | export default function poolAtAddress(address: string, wallet: Wallet): IPancakeV3Pool { 6 | return new Contract(address, POOL_ABI, wallet) as IPancakeV3Pool 7 | } 8 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/ISmartRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | pragma abicoder v2; 4 | 5 | import './ISelfPermit.sol'; 6 | import './IMulticall.sol'; 7 | import './IAgniRouterV3.sol'; 8 | import '@agniswap/v2-core/contracts/interfaces/IAgniRouterV2.sol'; 9 | 10 | 11 | interface ISmartRouter is IAgniRouterV3, IAgniRouterV2, IMulticall, ISelfPermit { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /periphery/contracts/libraries/TokenRatioSortOrder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity =0.7.6; 3 | 4 | library TokenRatioSortOrder { 5 | int256 constant NUMERATOR_MOST = 300; 6 | int256 constant NUMERATOR_MORE = 200; 7 | int256 constant NUMERATOR = 100; 8 | 9 | int256 constant DENOMINATOR_MOST = -300; 10 | int256 constant DENOMINATOR_MORE = -200; 11 | int256 constant DENOMINATOR = -100; 12 | } 13 | -------------------------------------------------------------------------------- /periphery/contracts/libraries/ChainId.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.0; 3 | 4 | /// @title Function for getting the current chain ID 5 | library ChainId { 6 | /// @dev Gets the current chain ID 7 | /// @return chainId The current chain ID 8 | function get() internal pure returns (uint256 chainId) { 9 | assembly { 10 | chainId := chainid() 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/contracts/libraries/FixedPoint96.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.4.0; 3 | 4 | /// @title FixedPoint96 5 | /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) 6 | /// @dev Used in SqrtPriceMath.sol 7 | library FixedPoint96 { 8 | uint8 internal constant RESOLUTION = 96; 9 | uint256 internal constant Q96 = 0x1000000000000000000000000; 10 | } 11 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/IWMNT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | 6 | /// @title Interface for WMNT 7 | interface IWMNT is IERC20 { 8 | /// @notice Deposit ether to get wrapped ether 9 | function deposit() external payable; 10 | 11 | /// @notice Withdraw wrapped ether to get ether 12 | function withdraw(uint256) external; 13 | } 14 | -------------------------------------------------------------------------------- /v2-protocol/deployments/mantleMainnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniFactory": "0xd7D3e1116277a0f8b6f23cc64D5Ea56982822Dde", 3 | "AgniRouter": "0x4CBA08a0880c502AB1e10CDC93Dbc74C23524ac7", 4 | "AgniFeeSetter": "0x63a7E6aC788167E166AA66689b90889500D3aBd3", 5 | "AgniFeeTo": "0xD8A4c759bC19cC3E90e7151f0ccfb3120175ee27", 6 | "WMNT": "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8", 7 | "INIT_CODE_PAIR_HASH": "0x9f069684a442182358aa78dcfcdb94306295a8aa99f3ae103bf1e5ba30bfa0de" 8 | } -------------------------------------------------------------------------------- /periphery/contracts/test/TestERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '@openzeppelin/contracts/drafts/ERC20Permit.sol'; 5 | 6 | contract TestERC20Metadata is ERC20Permit { 7 | constructor( 8 | uint256 amountToMint, 9 | string memory name, 10 | string memory symbol 11 | ) ERC20(name, symbol) ERC20Permit(name) { 12 | _mint(msg.sender, amountToMint); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /v2-protocol/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniFactory": "0x75F57C3a822cc37dd2453cAC3469a21361456BFb", 3 | "AgniRouter": "0x3E30894AaEB2ba741b8E2999604D1d01fF6244ea", 4 | "AgniFeeSetter": "0x7D515d229FF5b4b8f3Bc24391B5E1c897363d8D9", 5 | "AgniFeeTo": "0xB4ebe166513C578e33A8373f04339508bC7E8Cfb", 6 | "WMNT": "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF", 7 | "INIT_CODE_PAIR_HASH": "0x32c0c6de30723d6476d34f01d79ce2df1df1a7ce4ea97ab3d9284b60dd59e540" 8 | } -------------------------------------------------------------------------------- /periphery/contracts/libraries/PositionKey.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | library PositionKey { 5 | /// @dev Returns the key of the position in the core library 6 | function compute( 7 | address owner, 8 | int24 tickLower, 9 | int24 tickUpper 10 | ) internal pure returns (bytes32) { 11 | return keccak256(abi.encodePacked(owner, tickLower, tickUpper)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/ILMPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | interface ILMPool { 5 | function updatePosition(int24 tickLower, int24 tickUpper, int128 liquidityDelta) external; 6 | 7 | function getRewardGrowthInside( 8 | int24 tickLower, 9 | int24 tickUpper 10 | ) external view returns (uint256 rewardGrowthInsideX128); 11 | 12 | function accumulateReward(uint32 currTimestamp) external; 13 | } 14 | -------------------------------------------------------------------------------- /periphery/test/shared/ticks.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from 'ethers' 2 | 3 | export const getMinTick = (tickSpacing: number) => Math.ceil(-887272 / tickSpacing) * tickSpacing 4 | export const getMaxTick = (tickSpacing: number) => Math.floor(887272 / tickSpacing) * tickSpacing 5 | export const getMaxLiquidityPerTick = (tickSpacing: number) => 6 | BigNumber.from(2) 7 | .pow(128) 8 | .sub(1) 9 | .div((getMaxTick(tickSpacing) - getMinTick(tickSpacing)) / tickSpacing + 1) 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # agni-contracts 2 | This is smart contracts for Agni Protocol. 3 | 4 | ## Deployments 5 | 6 | 1. Add Key in `.env` file. It's a private key of the account that will deploy the contracts and should be gitignored. 7 | 2. mantleTestnet `KEY_TESTNET` or mantle `KEY_MAINNET` 8 | 3. add `ETHERSCAN_API_KEY` in `.env` file. It's an API key for etherscan. 9 | 4. `yarn` in root directory 10 | 5. `NETWORK=$NETWORK yarn zx deploy.mjs` where `$NETWORK` is either `mantleTestnet` or `hardhat` (for local testing) -------------------------------------------------------------------------------- /periphery/contracts/test/TestCallbackValidation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/CallbackValidation.sol'; 5 | 6 | contract TestCallbackValidation { 7 | function verifyCallback( 8 | address factory, 9 | address tokenA, 10 | address tokenB, 11 | uint24 fee 12 | ) external view returns (IAgniPool pool) { 13 | return CallbackValidation.verifyCallback(factory, tokenA, tokenB, fee); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /periphery/contracts/base/BlockTimestamp.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | /// @title Function for getting block timestamp 5 | /// @dev Base contract that is overridden for tests 6 | abstract contract BlockTimestamp { 7 | /// @dev Method that exists purely to be overridden for tests 8 | /// @return The current block timestamp 9 | function _blockTimestamp() internal view virtual returns (uint256) { 10 | return block.timestamp; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /periphery/contracts/base/ImmutableState.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/IImmutableState.sol'; 5 | 6 | /// @title Immutable state 7 | /// @notice Immutable state used by the swap router 8 | abstract contract ImmutableState is IImmutableState { 9 | /// @inheritdoc IImmutableState 10 | address public immutable override factoryV2; 11 | 12 | constructor(address _factoryV2) { 13 | factoryV2 = _factoryV2; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/IFarmBooster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | interface IFarmBooster { 5 | function getUserMultiplier(uint256 _tokenId) external view returns (uint256); 6 | 7 | function whiteList(uint256 _pid) external view returns (bool); 8 | 9 | function updatePositionBoostMultiplier(uint256 _tokenId) external returns (uint256 _multiplier); 10 | 11 | function removeBoostMultiplier(address _user, uint256 _tokenId, uint256 _pid) external; 12 | } 13 | -------------------------------------------------------------------------------- /masterchef/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "MasterChef": "0xE208968b22Cf710b06d10a0441Fa892d126f64df", 3 | "MasterChefV3Receiver": "0x527AEf62313b965034Dd759b96217022bEC011e4", 4 | "MasterChefToken": "0xd3b2241BfF9654195F814a15CbAc458C72Fa5084", 5 | "ExtraIncentivePool": "0x653A69006c1EAd4FB41Bce99942B2D9624A9F816", 6 | "IncentivePoolReceiver": "0xF7Ee63689b05B062Ebd15327CD80Cf81cC133fd0", 7 | "IncentiveToken": "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF", 8 | "WMNT": "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF" 9 | } -------------------------------------------------------------------------------- /periphery/contracts/test/Base64Test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import 'base64-sol/base64.sol'; 5 | 6 | contract Base64Test { 7 | function encode(bytes memory data) external pure returns (string memory) { 8 | return Base64.encode(data); 9 | } 10 | 11 | function getGasCostOfEncode(bytes memory data) external view returns (uint256) { 12 | uint256 gasBefore = gasleft(); 13 | Base64.encode(data); 14 | return gasBefore - gasleft(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /launchpad/deployments/mantleTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "ScoreCalculator": { 3 | "Proxy": "0x9Cecf546DC36A2DaA5eC7375C3cF35FEd1ADD7a2", 4 | "Admin": "0x077e4C7F653FFe83cb560d994aDFF5685b3F0e6B", 5 | "Implementation": "0xF3FaF04d1FeF0bce0a3cCD7a817810B9071fDa36" 6 | }, 7 | "StakingPool": "0x31Fa04284049BD9C3Aff46503482270f0Be4BC5E", 8 | "IdoPoolTemplate": "0xae411e11D9fA2773CEaC200cC2C73F17324Fc93B", 9 | "IdoPoolFactory": "0xBfdb61b73Ad4647f3EcBeeeE5e875F081C486d53", 10 | "InsurancePool": "0xccc6A1C40BCFd5458CE3ebB731644fc62E3041e9" 11 | } -------------------------------------------------------------------------------- /core/contracts/test/UnsafeMathEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/UnsafeMath.sol'; 5 | 6 | contract UnsafeMathEchidnaTest { 7 | function checkDivRoundingUp(uint256 x, uint256 d) external pure { 8 | require(d > 0); 9 | uint256 z = UnsafeMath.divRoundingUp(x, d); 10 | uint256 diff = z - (x / d); 11 | if (x % d == 0) { 12 | assert(diff == 0); 13 | } else { 14 | assert(diff == 1); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /launchpad/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "ScoreCalculator": { 3 | "Proxy": "0x64eD9E7e7eF8b19157877DDEe088D2C5DbAc632f", 4 | "Admin": "0x828722E61c29E0A956e3861A777284f50C949E99", 5 | "Implementation": "0x824b4193e6f8af48923dAeC847F17305255A81e8" 6 | }, 7 | "StakingPool": "0xB41A4760655DCD21FFd3190ff71173220554355b", 8 | "IdoPoolTemplate": "0xc91acFE288F2D558F2e524b4F5365A2b889F45CC", 9 | "IdoPoolFactory": "0xD9495cADc3a14f16230ff2404a6980b00cd981c2", 10 | "InsurancePool": "0x59CfC9dcCF9b628DeE6A176C65DA03eCEdD29EbE" 11 | } -------------------------------------------------------------------------------- /periphery/test/shared/encodePriceSqrt.ts: -------------------------------------------------------------------------------- 1 | import bn from 'bignumber.js' 2 | import { BigNumber, BigNumberish } from 'ethers' 3 | 4 | bn.config({ EXPONENTIAL_AT: 999999, DECIMAL_PLACES: 40 }) 5 | 6 | // returns the sqrt price as a 64x96 7 | export function encodePriceSqrt(reserve1: BigNumberish, reserve0: BigNumberish): BigNumber { 8 | return BigNumber.from( 9 | new bn(reserve1.toString()) 10 | .div(reserve0.toString()) 11 | .sqrt() 12 | .multipliedBy(new bn(2).pow(96)) 13 | .integerValue(3) 14 | .toString() 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /core/contracts/test/LiquidityMathTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/LiquidityMath.sol'; 5 | 6 | contract LiquidityMathTest { 7 | function addDelta(uint128 x, int128 y) external pure returns (uint128 z) { 8 | return LiquidityMath.addDelta(x, y); 9 | } 10 | 11 | function getGasCostOfAddDelta(uint128 x, int128 y) external view returns (uint256) { 12 | uint256 gasBefore = gasleft(); 13 | LiquidityMath.addDelta(x, y); 14 | return gasBefore - gasleft(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /periphery/contracts/test/MockTimeSwapRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | import '../SwapRouter.sol'; 6 | 7 | contract MockTimeSwapRouter is SwapRouter { 8 | uint256 time; 9 | 10 | constructor(address _deployer, address _factory, address _WMNT) SwapRouter(_deployer, _factory, _WMNT) {} 11 | 12 | function _blockTimestamp() internal view override returns (uint256) { 13 | return time; 14 | } 15 | 16 | function setTime(uint256 _time) external { 17 | time = _time; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/contracts/test/FullMathTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/FullMath.sol'; 5 | 6 | contract FullMathTest { 7 | function mulDiv( 8 | uint256 x, 9 | uint256 y, 10 | uint256 z 11 | ) external pure returns (uint256) { 12 | return FullMath.mulDiv(x, y, z); 13 | } 14 | 15 | function mulDivRoundingUp( 16 | uint256 x, 17 | uint256 y, 18 | uint256 z 19 | ) external pure returns (uint256) { 20 | return FullMath.mulDivRoundingUp(x, y, z); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /periphery/contracts/test/TickLensTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | pragma abicoder v2; 4 | 5 | import '@agniswap/core/contracts/interfaces/IAgniPool.sol'; 6 | import '../lens/TickLens.sol'; 7 | 8 | /// @title Tick Lens contract 9 | contract TickLensTest is TickLens { 10 | function getGasCostOfGetPopulatedTicksInWord(address pool, int16 tickBitmapIndex) external view returns (uint256) { 11 | uint256 gasBefore = gasleft(); 12 | getPopulatedTicksInWord(pool, tickBitmapIndex); 13 | return gasBefore - gasleft(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IAgniRouterV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IAgniRouterV2 { 5 | function swapExactTokensForTokens( 6 | uint256 amountIn, 7 | uint256 amountOutMin, 8 | address[] calldata path, 9 | address to 10 | ) external payable returns (uint256 amountOut); 11 | 12 | function swapTokensForExactTokens( 13 | uint256 amountOut, 14 | uint256 amountInMax, 15 | address[] calldata path, 16 | address to 17 | ) external payable returns (uint256 amountIn); 18 | } 19 | -------------------------------------------------------------------------------- /periphery/deployments/mantleTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "WMNT": "0xEa12Be2389c2254bAaD383c6eD1fa1e15202b52A", 3 | "SwapRouter": "0xe2DB835566F8677d6889ffFC4F3304e8Df5Fc1df", 4 | "QuoterV2": "0x49C8bb51C6bb791e8D6C31310cE0C14f68492991", 5 | "TickLens": "0x0DC832e8cA4a7E1CE073096709474A5422029DB3", 6 | "NFTDescriptor": "0x8002eb63E37728ddf15bd42Bf2607CBbBa714b3f", 7 | "NonfungibleTokenPositionDescriptor": "0xDc7E9B3E927f2880CEa359e659321F9d232aCb2c", 8 | "NonfungiblePositionManager": "0xb04a19EF7853c52EDe6FBb28F8FfBecb73329eD7", 9 | "AgniInterfaceMulticall": "0xF9Ae3Cc6D6483722b94d7075C9B366bcbbbab9d3" 10 | } -------------------------------------------------------------------------------- /periphery/contracts/test/PoolTicksCounterTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | import '@agniswap/core/contracts/interfaces/IAgniPool.sol'; 3 | 4 | pragma solidity >=0.6.0; 5 | 6 | import '../libraries/PoolTicksCounter.sol'; 7 | 8 | contract PoolTicksCounterTest { 9 | using PoolTicksCounter for IAgniPool; 10 | 11 | function countInitializedTicksCrossed( 12 | IAgniPool pool, 13 | int24 tickBefore, 14 | int24 tickAfter 15 | ) external view returns (uint32 initializedTicksCrossed) { 16 | return pool.countInitializedTicksCrossed(tickBefore, tickAfter); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IPeripheryImmutableState.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Immutable state 5 | /// @notice Functions that return immutable state of the router 6 | interface IPeripheryImmutableState { 7 | /// @return Returns the address of the Agni deployer 8 | function deployer() external view returns (address); 9 | 10 | /// @return Returns the address of the Agni factory 11 | function factory() external view returns (address); 12 | 13 | /// @return Returns the address of WMNT 14 | function WMNT() external view returns (address); 15 | } 16 | -------------------------------------------------------------------------------- /common/utils.ts: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | 4 | function getContractAddresses(network, filename) { 5 | if (filename == "") { 6 | return JSON.parse( 7 | fs.readFileSync(`${process.cwd()}/deployments/${network}.json`).toString() 8 | ); 9 | } 10 | 11 | return JSON.parse(fs.readFileSync(filename).toString()); 12 | } 13 | 14 | function writeContractAddresses(network, contractAddresses) { 15 | fs.writeFileSync( 16 | `${process.cwd()}/deployments/${network}.json`, 17 | JSON.stringify(contractAddresses, null, 2) // Indent 2 spaces 18 | ); 19 | } 20 | 21 | module.exports = { 22 | getContractAddresses, 23 | writeContractAddresses, 24 | }; -------------------------------------------------------------------------------- /farmbooster/contracts/interfaces/IAgniPool.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface IAgniPool { 5 | function userInfo( 6 | address _user 7 | ) external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool, uint256); 8 | 9 | function getPricePerFullShare() external view returns (uint256); 10 | 11 | function totalLockedAmount() external view returns (uint256); 12 | 13 | function totalShares() external view returns (uint256); 14 | 15 | function BOOST_WEIGHT() external view returns (uint256); 16 | 17 | function MAX_LOCK_DURATION() external view returns (uint256); 18 | } -------------------------------------------------------------------------------- /farmbooster/contracts/interfaces/IMasterChefV3.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.9; 3 | 4 | interface IMasterChefV3 { 5 | function userPositionInfos( 6 | uint256 _tokenId 7 | ) external view returns (uint128, uint128, int24, int24, uint256, uint256, address, uint256, uint256); 8 | 9 | function poolInfo( 10 | uint256 _pid 11 | ) external view returns (uint256, address, address, address, uint24, uint256, uint256); 12 | 13 | function getBoostMultiplier(address _user, uint256 _pid) external view returns (uint256); 14 | 15 | function updateBoostMultiplier(uint256 _tokenId, uint256 _newMultiplier) external; 16 | } -------------------------------------------------------------------------------- /periphery/scripts/pool_address.ts: -------------------------------------------------------------------------------- 1 | const c = require("../test/shared/computePoolAddress"); 2 | 3 | const token0 = "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE"; 4 | const token1 = "0x78c1b0c915c4faa5fffa6cabf0219da63d7f4cb8"; 5 | const deployer = "0xDc295A765DbB51b0948a86f835E7Ca37Ba4F3e03"; 6 | const fee = 500; 7 | 8 | 9 | async function main() { 10 | let result = await c.computePoolAddress(deployer, [token0, token1], fee); 11 | console.log(result); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /periphery/contracts/libraries/Constants.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | /// @title Constant state 5 | /// @notice Constant state used by the swap router 6 | library Constants { 7 | /// @dev Used for identifying cases when this contract's balance of a token is to be used 8 | uint256 internal constant CONTRACT_BALANCE = 0; 9 | 10 | /// @dev Used as a flag for identifying msg.sender, saves gas by sending more 0 bytes 11 | address internal constant MSG_SENDER = address(1); 12 | 13 | /// @dev Used as a flag for identifying address(this), saves gas by sending more 0 bytes 14 | address internal constant ADDRESS_THIS = address(2); 15 | } 16 | -------------------------------------------------------------------------------- /core/contracts/test/BitMathEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/BitMath.sol'; 5 | 6 | contract BitMathEchidnaTest { 7 | function mostSignificantBitInvariant(uint256 input) external pure { 8 | uint8 msb = BitMath.mostSignificantBit(input); 9 | assert(input >= (uint256(2)**msb)); 10 | assert(msb == 255 || input < uint256(2)**(msb + 1)); 11 | } 12 | 13 | function leastSignificantBitInvariant(uint256 input) external pure { 14 | uint8 lsb = BitMath.leastSignificantBit(input); 15 | assert(input & (uint256(2)**lsb) != 0); 16 | assert(input & (uint256(2)**lsb - 1) == 0); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.7.0; 3 | 4 | import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; 5 | 6 | /// @title IERC20Metadata 7 | /// @title Interface for ERC20 Metadata 8 | /// @notice Extension to IERC20 that includes token metadata 9 | interface IERC20Metadata is IERC20 { 10 | /// @return The name of the token 11 | function name() external view returns (string memory); 12 | 13 | /// @return The symbol of the token 14 | function symbol() external view returns (string memory); 15 | 16 | /// @return The number of decimal places the token has 17 | function decimals() external view returns (uint8); 18 | } 19 | -------------------------------------------------------------------------------- /core/contracts/libraries/LiquidityMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Math library for liquidity 5 | library LiquidityMath { 6 | /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows 7 | /// @param x The liquidity before change 8 | /// @param y The delta by which liquidity should be changed 9 | /// @return z The liquidity delta 10 | function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) { 11 | if (y < 0) { 12 | require((z = x - uint128(-y)) < x, 'LS'); 13 | } else { 14 | require((z = x + uint128(y)) >= x, 'LA'); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /v2-protocol/contracts/libraries/SafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) 5 | 6 | library SafeMath { 7 | function add(uint256 x, uint256 y) internal pure returns (uint256 z) { 8 | require((z = x + y) >= x, "ds-math-add-overflow"); 9 | } 10 | 11 | function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { 12 | require((z = x - y) <= x, "ds-math-sub-underflow"); 13 | } 14 | 15 | function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { 16 | require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /v2-protocol/contracts/libraries/UQ112x112.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 5 | 6 | // range: [0, 2**112 - 1] 7 | // resolution: 1 / 2**112 8 | 9 | library UQ112x112 { 10 | uint224 constant Q112 = 2**112; 11 | 12 | // encode a uint112 as a UQ112x112 13 | function encode(uint112 y) internal pure returns (uint224 z) { 14 | z = uint224(y) * Q112; // never overflows 15 | } 16 | 17 | // divide a UQ112x112 by a uint112, returning a UQ112x112 18 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 19 | z = x / uint224(y); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /farmbooster/scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers,upgrades } from "hardhat"; 2 | const utils = require("../common/utils"); 3 | import dotenv from "dotenv"; 4 | dotenv.config(); 5 | 6 | async function main() { 7 | const FarmBooster = await ethers.getContractFactory("FarmBooster"); 8 | const farmBooster = await FarmBooster.deploy(); 9 | console.log("farmBooster", farmBooster.address); 10 | 11 | let contractAddresses = { 12 | FarmBooster: farmBooster.address, 13 | }; 14 | await utils.writeContractAddresses(contractAddresses); 15 | } 16 | 17 | // We recommend this pattern to be able to use async/await everywhere 18 | // and properly handle errors. 19 | main().catch((error) => { 20 | console.error(error); 21 | process.exitCode = 1; 22 | }); 23 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/IIncentivePool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | interface IIncentivePool { 5 | function latestPeriodEndTime() external view returns (uint256); 6 | 7 | function latestPeriodStartTime() external view returns (uint256); 8 | 9 | function upkeep(uint256 amount, uint256 duration) external; 10 | 11 | function getPoolByTokenId(uint256 _tokenId) external view returns (address); 12 | 13 | function getLiquidityByTokenId(uint256 _tokenId) external view returns (uint256 , uint256 ); 14 | 15 | function getLastRewardTimeTimeByTokenId(uint256 _tokenId) external view returns (uint32); 16 | 17 | function harvest(uint256 _tokenId) external returns (uint256 reward); 18 | } -------------------------------------------------------------------------------- /periphery/contracts/test/NonfungiblePositionManagerPositionsGasTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/INonfungiblePositionManager.sol'; 5 | 6 | contract NonfungiblePositionManagerPositionsGasTest { 7 | INonfungiblePositionManager immutable nonfungiblePositionManager; 8 | 9 | constructor(INonfungiblePositionManager _nonfungiblePositionManager) { 10 | nonfungiblePositionManager = _nonfungiblePositionManager; 11 | } 12 | 13 | function getGasCostOfPositions(uint256 tokenId) external view returns (uint256) { 14 | uint256 gasBefore = gasleft(); 15 | nonfungiblePositionManager.positions(tokenId); 16 | return gasBefore - gasleft(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /core/contracts/libraries/UnsafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Math functions that do not check inputs or outputs 5 | /// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks 6 | library UnsafeMath { 7 | /// @notice Returns ceil(x / y) 8 | /// @dev division by 0 has unspecified behavior, and must be checked externally 9 | /// @param x The dividend 10 | /// @param y The divisor 11 | /// @return z The quotient, ceil(x / y) 12 | function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) { 13 | assembly { 14 | z := add(div(x, y), gt(mod(x, y), 0)) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /periphery/contracts/test/MockTimeNonfungiblePositionManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | import '../NonfungiblePositionManager.sol'; 6 | 7 | contract MockTimeNonfungiblePositionManager is NonfungiblePositionManager { 8 | uint256 time; 9 | 10 | constructor( 11 | address _deployer, 12 | address _factory, 13 | address _WMNT, 14 | address _tokenDescriptor 15 | ) NonfungiblePositionManager(_deployer, _factory, _WMNT, _tokenDescriptor) {} 16 | 17 | function _blockTimestamp() internal view override returns (uint256) { 18 | return time; 19 | } 20 | 21 | function setTime(uint256 _time) external { 22 | time = _time; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IMulticall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | pragma abicoder v2; 4 | 5 | /// @title Multicall interface 6 | /// @notice Enables calling multiple methods in a single call to the contract 7 | interface IMulticall { 8 | /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed 9 | /// @dev The `msg.value` should not be trusted for any method callable from multicall. 10 | /// @param data The encoded function data for each of the calls to make to this contract 11 | /// @return results The results from each of the calls passed in via data 12 | function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); 13 | } 14 | -------------------------------------------------------------------------------- /v2-protocol/contracts/libraries/Math.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | // a library for performing various math operations 5 | 6 | library Math { 7 | function min(uint256 x, uint256 y) internal pure returns (uint256 z) { 8 | z = x < y ? x : y; 9 | } 10 | 11 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 12 | function sqrt(uint256 y) internal pure returns (uint256 z) { 13 | if (y > 3) { 14 | z = y; 15 | uint256 x = y / 2 + 1; 16 | while (x < z) { 17 | z = x; 18 | x = (y / x + x) / 2; 19 | } 20 | } else if (y != 0) { 21 | z = 1; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/external/IWMNT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; 5 | 6 | /// @title Interface for WMNT 7 | interface IWMNT is IERC20 { 8 | /// @notice Deposit ether to get wrapped ether 9 | function deposit() external payable; 10 | 11 | /// @notice Withdraw wrapped ether to get ether 12 | function withdraw(uint256) external; 13 | 14 | function totalSupply() override external view returns (uint); 15 | 16 | function approve(address guy, uint wad) override external returns (bool); 17 | 18 | function transfer(address dst, uint wad) override external returns (bool); 19 | 20 | function transferFrom(address src, address dst, uint wad) override external returns (bool); 21 | } -------------------------------------------------------------------------------- /farmbooster/scripts/verify.ts: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const {network} = require("hardhat"); 3 | const utils = require("../../common/utils"); 4 | import dotenv from "dotenv"; 5 | dotenv.config(); 6 | 7 | async function main() { 8 | let networkName = network.name; 9 | let contractAddresses = utils.getContractAddresses(networkName,""); 10 | console.log("multicall3 contract addresses:", contractAddresses); 11 | 12 | await hre.run("verify:verify", { 13 | address: contractAddresses.Multicall3, 14 | contract: "contracts/Multicall3.sol:Multicall3", 15 | constructorArguments: [], 16 | }); 17 | } 18 | 19 | // We recommend this pattern to be able to use async/await everywhere 20 | // and properly handle errors. 21 | main().catch((error) => { 22 | console.error(error); 23 | process.exitCode = 1; 24 | }); 25 | -------------------------------------------------------------------------------- /multicall3/scripts/verify.ts: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const {network} = require("hardhat"); 3 | const utils = require("../../common/utils"); 4 | import dotenv from "dotenv"; 5 | dotenv.config(); 6 | 7 | async function main() { 8 | let networkName = network.name; 9 | let contractAddresses = utils.getContractAddresses(networkName,""); 10 | console.log("multicall3 contract addresses:", contractAddresses); 11 | 12 | await hre.run("verify:verify", { 13 | address: contractAddresses.Multicall3, 14 | contract: "contracts/Multicall3.sol:Multicall3", 15 | constructorArguments: [], 16 | }); 17 | } 18 | 19 | // We recommend this pattern to be able to use async/await everywhere 20 | // and properly handle errors. 21 | main().catch((error) => { 22 | console.error(error); 23 | process.exitCode = 1; 24 | }); 25 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/INonfungiblePositionManagerStruct.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.10; 3 | 4 | interface INonfungiblePositionManagerStruct { 5 | struct IncreaseLiquidityParams { 6 | uint256 tokenId; 7 | uint256 amount0Desired; 8 | uint256 amount1Desired; 9 | uint256 amount0Min; 10 | uint256 amount1Min; 11 | uint256 deadline; 12 | } 13 | 14 | struct DecreaseLiquidityParams { 15 | uint256 tokenId; 16 | uint128 liquidity; 17 | uint256 amount0Min; 18 | uint256 amount1Min; 19 | uint256 deadline; 20 | } 21 | 22 | struct CollectParams { 23 | uint256 tokenId; 24 | address recipient; 25 | uint128 amount0Max; 26 | uint128 amount1Max; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /multicall3/common/utils.ts: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | import dotenv from "dotenv"; 3 | dotenv.config(); 4 | 5 | function getContractAddresses(filename) { 6 | if (filename==""){ 7 | return JSON.parse( 8 | fs 9 | .readFileSync( 10 | `${process.cwd()}/deployments/${process.env.NETWORK}.json` 11 | ) 12 | .toString() 13 | ); 14 | } 15 | 16 | return JSON.parse( 17 | fs 18 | .readFileSync(filename) 19 | .toString() 20 | ); 21 | } 22 | 23 | function writeContractAddresses(contractAddresses) { 24 | fs.writeFileSync( 25 | `${process.cwd()}/deployments/${process.env.NETWORK}.json`, 26 | JSON.stringify(contractAddresses, null, 2) // Indent 2 spaces 27 | ); 28 | } 29 | 30 | module.exports = { 31 | getContractAddresses, 32 | writeContractAddresses, 33 | }; 34 | -------------------------------------------------------------------------------- /periphery/contracts/test/TestMulticall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | import '../base/Multicall.sol'; 6 | 7 | contract TestMulticall is Multicall { 8 | function functionThatRevertsWithError(string memory error) external pure { 9 | revert(error); 10 | } 11 | 12 | struct Tuple { 13 | uint256 a; 14 | uint256 b; 15 | } 16 | 17 | function functionThatReturnsTuple(uint256 a, uint256 b) external pure returns (Tuple memory tuple) { 18 | tuple = Tuple({b: a, a: b}); 19 | } 20 | 21 | uint256 public paid; 22 | 23 | function pays() external payable { 24 | paid += msg.value; 25 | } 26 | 27 | function returnSender() external view returns (address) { 28 | return msg.sender; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /periphery/contracts/base/PeripheryImmutableState.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/IPeripheryImmutableState.sol'; 5 | 6 | /// @title Immutable state 7 | /// @notice Immutable state used by periphery contracts 8 | abstract contract PeripheryImmutableState is IPeripheryImmutableState { 9 | /// @inheritdoc IPeripheryImmutableState 10 | address public immutable override deployer; 11 | /// @inheritdoc IPeripheryImmutableState 12 | address public immutable override factory; 13 | /// @inheritdoc IPeripheryImmutableState 14 | address public immutable override WMNT; 15 | 16 | constructor(address _deployer, address _factory, address _WMNT) { 17 | deployer = _deployer; 18 | factory = _factory; 19 | WMNT = _WMNT; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/IAgniPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.10; 3 | 4 | interface IAgniPool { 5 | function factory() external view returns (address); 6 | 7 | function token0() external view returns (address); 8 | 9 | function token1() external view returns (address); 10 | 11 | function fee() external view returns (uint24); 12 | 13 | function lmPool() external view returns (address); 14 | 15 | function slot0() 16 | external 17 | view 18 | returns ( 19 | uint160 sqrtPriceX96, 20 | int24 tick, 21 | uint16 observationIndex, 22 | uint16 observationCardinality, 23 | uint16 observationCardinalityNext, 24 | uint32 feeProtocol, 25 | bool unlocked 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /periphery/contracts/SmartRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | import './SwapRouter.sol'; 6 | import './base/Multicall.sol'; 7 | import './base/SelfPermit.sol'; 8 | import './interfaces/ISmartRouter.sol'; 9 | import './AgniRouterV2.sol'; 10 | import './AgniRouterV3.sol'; 11 | import './base/PeripheryImmutableState.sol'; 12 | import './base/ImmutableState.sol'; 13 | 14 | contract SmartRouter is 15 | ISmartRouter, 16 | AgniRouterV3, 17 | AgniRouterV2, 18 | Multicall, 19 | SelfPermit 20 | { 21 | 22 | constructor( 23 | address _factoryV2, 24 | address _deployer, 25 | address _factoryV3, 26 | address _WMNT 27 | ) ImmutableState(_factoryV2) PeripheryImmutableState(_deployer, _factoryV3, _WMNT) {} 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/contracts/interfaces/IAgniPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import './pool/IAgniPoolImmutables.sol'; 5 | import './pool/IAgniPoolState.sol'; 6 | import './pool/IAgniPoolDerivedState.sol'; 7 | import './pool/IAgniPoolActions.sol'; 8 | import './pool/IAgniPoolOwnerActions.sol'; 9 | import './pool/IAgniPoolEvents.sol'; 10 | 11 | /// @title The interface for a Agni Pool 12 | /// @notice A Agni pool facilitates swapping and automated market making between any two assets that strictly conform 13 | /// to the ERC20 specification 14 | /// @dev The pool interface is broken up into many smaller pieces 15 | interface IAgniPool is 16 | IAgniPoolImmutables, 17 | IAgniPoolState, 18 | IAgniPoolDerivedState, 19 | IAgniPoolActions, 20 | IAgniPoolOwnerActions, 21 | IAgniPoolEvents 22 | { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /multicall3/scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers, upgrades, network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | import dotenv from "dotenv"; 4 | dotenv.config(); 5 | 6 | async function main() { 7 | const networkName = await network.name; 8 | console.log("Network name=", networkName); 9 | 10 | const Multicall3 = await ethers.getContractFactory("Multicall3"); 11 | const multicall3 = await Multicall3.deploy(); 12 | console.log("multicall3", multicall3.address); 13 | 14 | let contractAddresses = { 15 | Multicall3: multicall3.address 16 | }; 17 | await utils.writeContractAddresses(networkName, contractAddresses); 18 | } 19 | 20 | // We recommend this pattern to be able to use async/await everywhere 21 | // and properly handle errors. 22 | main().catch((error) => { 23 | console.error(error); 24 | process.exitCode = 1; 25 | }); 26 | -------------------------------------------------------------------------------- /core/contracts/test/MockTimeAgniPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../AgniPool.sol'; 5 | 6 | // used for testing time dependent behavior 7 | contract MockTimeAgniPool is AgniPool { 8 | // Monday, October 5, 2020 9:00:00 AM GMT-05:00 9 | uint256 public time = 1601906400; 10 | 11 | function setFeeGrowthGlobal0X128(uint256 _feeGrowthGlobal0X128) external { 12 | feeGrowthGlobal0X128 = _feeGrowthGlobal0X128; 13 | } 14 | 15 | function setFeeGrowthGlobal1X128(uint256 _feeGrowthGlobal1X128) external { 16 | feeGrowthGlobal1X128 = _feeGrowthGlobal1X128; 17 | } 18 | 19 | function advanceTime(uint256 by) external { 20 | time += by; 21 | } 22 | 23 | function _blockTimestamp() internal view override returns (uint32) { 24 | return uint32(time); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /periphery/deployments/mantleMainnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "WMNT": "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8", 3 | "SwapRouter": "0x319B69888b0d11cEC22caA5034e25FfFBDc88421", 4 | "Quoter": "0x9488C05a7b75a6FefdcAE4f11a33467bcBA60177", 5 | "QuoterV2": "0xc4aaDc921E1cdb66c5300Bc158a313292923C0cb", 6 | "TickLens": "0xEcDbA665AA209247CD334d0D037B913528a7bf67", 7 | "NFTDescriptor": "0x70153a35c3005385b45c47cDcfc7197c1a22477a", 8 | "NonfungibleTokenPositionDescriptor": "0xcb814b767D41b4BD94dA6Abb860D25b607ad5764", 9 | "NonfungiblePositionManager": "0x218bf598D1453383e2F4AA7b14fFB9BfB102D637", 10 | "AgniInterfaceMulticall": "0xBE592EFcF174b3E0E4208DC8c1658822d017568f", 11 | "mixedRouteQuoterV1": "0xcdbd1c6cfc89Af8a518E23B0C71996B90a12Befc", 12 | "smartRouterHelper": "0xb0Bcbe0d2B197b7a8Fb7e66d6a0dD6a91cB985d6", 13 | "smartRouter": "0xB52b1F5e08c04a8c33F4C7363fa2DE23B9BC169f" 14 | } -------------------------------------------------------------------------------- /masterchef/contracts/interfaces/IMasterChefV3.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | interface IMasterChefV3 { 5 | function latestPeriodEndTime() external view returns (uint256); 6 | 7 | function latestPeriodStartTime() external view returns (uint256); 8 | 9 | function upkeep(uint256 amount, uint256 duration, bool withUpdate) external; 10 | 11 | function getPoolByTokenId(uint256 _tokenId) external view returns (address); 12 | 13 | function getOwnerByTokenId(uint256 _tokenId) external view returns (address); 14 | 15 | function getLiquidityByTokenId(uint256 _tokenId) external view returns (uint256 , uint256 ); 16 | 17 | function getLastRewardTimeTimeByTokenId(uint256 _tokenId) external view returns (uint32); 18 | 19 | function getPositionTickByTokenId(uint256 _tokenId) external view returns (int24, int24 ); 20 | } 21 | -------------------------------------------------------------------------------- /periphery/deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "WMNT": "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF", 3 | "SwapRouter": "0xe38cfa32cCd918d94E2e20230dFaD1A4Fd8aEF16", 4 | "Quoter": "0xA82F8dC4704d3512b120de70480219761F24B6Eb", 5 | "QuoterV2": "0x9Da17239a4170f50A5A2c11813BD0C601b5c9693", 6 | "TickLens": "0xB4EB98c6d7D4807033Ae6195241ef7A839070748", 7 | "NFTDescriptor": "0x7C20eE7CC3230003401cC19BF076871Aedf39856", 8 | "NonfungibleTokenPositionDescriptor": "0x497bd1C86a1088e80f58EaA13de8C81aB70a4e79", 9 | "NonfungiblePositionManager": "0x71959543c31EC4d68D9D6C492Bf69A1C174bb394", 10 | "AgniInterfaceMulticall": "0x49b05721B9615dC1811E20F47D5700dA2d6Ed429", 11 | "mixedRouteQuoterV1": "0xE1E898d8C7519440d6F8c2B674642A9a617eD02c", 12 | "smartRouterHelper": "0x8A168c3E24Ea84AcEb4E2dDD56Ff74456dCf3Ed8", 13 | "smartRouter": "0xb5Dc27be0a565A4A80440f41c74137001920CB22" 14 | } -------------------------------------------------------------------------------- /periphery/contracts/interfaces/INonfungibleTokenPositionDescriptor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import './INonfungiblePositionManager.sol'; 5 | 6 | /// @title Describes position NFT tokens via URI 7 | interface INonfungibleTokenPositionDescriptor { 8 | /// @notice Produces the URI describing a particular token ID for a position manager 9 | /// @dev Note this URI may be a data: URI with the JSON contents directly inlined 10 | /// @param positionManager The position manager for which to describe the token 11 | /// @param tokenId The ID of the token for which to produce a description, which may not be valid 12 | /// @return The URI of the ERC721-compliant metadata 13 | function tokenURI(INonfungiblePositionManager positionManager, uint256 tokenId) 14 | external 15 | view 16 | returns (string memory); 17 | } 18 | -------------------------------------------------------------------------------- /periphery/contracts/test/TestERC20PermitAllowed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import './TestERC20.sol'; 5 | import '../interfaces/external/IERC20PermitAllowed.sol'; 6 | 7 | // has a fake permit that just uses the other signature type for type(uint256).max 8 | contract TestERC20PermitAllowed is TestERC20, IERC20PermitAllowed { 9 | constructor(uint256 amountToMint) TestERC20(amountToMint) {} 10 | 11 | function permit( 12 | address holder, 13 | address spender, 14 | uint256 nonce, 15 | uint256 expiry, 16 | bool allowed, 17 | uint8 v, 18 | bytes32 r, 19 | bytes32 s 20 | ) external override { 21 | require(this.nonces(holder) == nonce, 'TestERC20PermitAllowed::permit: wrong nonce'); 22 | permit(holder, spender, allowed ? type(uint256).max : 0, expiry, v, r, s); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IAgniFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IAgniFactory { 5 | event PairCreated(address indexed token0, address indexed token1, address pair, uint256); 6 | 7 | function feeTo() external view returns (address); 8 | 9 | function feeToSetter() external view returns (address); 10 | 11 | function getPair(address tokenA, address tokenB) external view returns (address pair); 12 | 13 | function allPairs(uint256) external view returns (address pair); 14 | 15 | function allPairsLength() external view returns (uint256); 16 | 17 | function createPair(address tokenA, address tokenB) external returns (address pair); 18 | 19 | function setFeeTo(address) external; 20 | 21 | function setFeeToSetter(address) external; 22 | 23 | function INIT_CODE_PAIR_HASH() external view returns (bytes32); 24 | } 25 | -------------------------------------------------------------------------------- /periphery/contracts/test/TestPositionNFTOwner.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/external/IERC1271.sol'; 5 | 6 | contract TestPositionNFTOwner is IERC1271 { 7 | address public owner; 8 | 9 | function setOwner(address _owner) external { 10 | owner = _owner; 11 | } 12 | 13 | function isValidSignature(bytes32 hash, bytes memory signature) external view override returns (bytes4 magicValue) { 14 | bytes32 r; 15 | bytes32 s; 16 | uint8 v; 17 | assembly { 18 | r := mload(add(signature, 0x20)) 19 | s := mload(add(signature, 0x40)) 20 | v := byte(0, mload(add(signature, 0x60))) 21 | } 22 | if (ecrecover(hash, v, r, s) == owner) { 23 | return bytes4(0x1626ba7e); 24 | } else { 25 | return bytes4(0); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/contracts/test/BitMathTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/BitMath.sol'; 5 | 6 | contract BitMathTest { 7 | function mostSignificantBit(uint256 x) external pure returns (uint8 r) { 8 | return BitMath.mostSignificantBit(x); 9 | } 10 | 11 | function getGasCostOfMostSignificantBit(uint256 x) external view returns (uint256) { 12 | uint256 gasBefore = gasleft(); 13 | BitMath.mostSignificantBit(x); 14 | return gasBefore - gasleft(); 15 | } 16 | 17 | function leastSignificantBit(uint256 x) external pure returns (uint8 r) { 18 | return BitMath.leastSignificantBit(x); 19 | } 20 | 21 | function getGasCostOfLeastSignificantBit(uint256 x) external view returns (uint256) { 22 | uint256 gasBefore = gasleft(); 23 | BitMath.leastSignificantBit(x); 24 | return gasBefore - gasleft(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /launchpad/contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.7.6; 3 | 4 | interface IERC20 { 5 | event Approval(address indexed owner, address indexed spender, uint value); 6 | event Transfer(address indexed from, address indexed to, uint value); 7 | 8 | function name() external pure returns (string memory); 9 | function symbol() external pure returns (string memory); 10 | function decimals() external pure returns (uint8); 11 | function totalSupply() external view returns (uint); 12 | function balanceOf(address owner) external view returns (uint); 13 | function allowance(address owner, address spender) external view returns (uint); 14 | 15 | function approve(address spender, uint value) external returns (bool); 16 | function transfer(address to, uint value) external returns (bool); 17 | function transferFrom(address from, address to, uint value) external returns (bool); 18 | } -------------------------------------------------------------------------------- /periphery/contracts/interfaces/external/IERC1271.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Interface for verifying contract-based account signatures 5 | /// @notice Interface that verifies provided signature for the data 6 | /// @dev Interface defined by EIP-1271 7 | interface IERC1271 { 8 | /// @notice Returns whether the provided signature is valid for the provided data 9 | /// @dev MUST return the bytes4 magic value 0x1626ba7e when function passes. 10 | /// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5). 11 | /// MUST allow external calls. 12 | /// @param hash Hash of the data to be signed 13 | /// @param signature Signature byte array associated with _data 14 | /// @return magicValue The bytes4 magic value 0x1626ba7e 15 | function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); 16 | } 17 | -------------------------------------------------------------------------------- /masterchef/contracts/utils/Multicall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.10; 3 | 4 | /// @title Multicall 5 | /// @notice Enables calling multiple methods in a single call to the contract 6 | contract Multicall { 7 | function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) { 8 | results = new bytes[](data.length); 9 | for (uint256 i = 0; i < data.length; i++) { 10 | (bool success, bytes memory result) = address(this).delegatecall(data[i]); 11 | 12 | if (!success) { 13 | // Next 5 lines from https://ethereum.stackexchange.com/a/83577 14 | if (result.length < 68) revert(); 15 | assembly { 16 | result := add(result, 0x04) 17 | } 18 | revert(abi.decode(result, (string))); 19 | } 20 | 21 | results[i] = result; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /masterchef/scripts/deposit_wmnt.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | const provider = new ethers.providers.JsonRpcProvider(); 4 | const fs = require("fs"); 5 | const abi = JSON.parse(fs.readFileSync("./abi/WMNT.json", "utf8")); 6 | 7 | async function main() { 8 | const networkName = await network.name; 9 | console.log("Network name=", networkName); 10 | 11 | let contractAddresses = utils.getContractAddresses(networkName, ""); 12 | 13 | const accounts = await hre.ethers.getSigners(); 14 | const wmntContract = new ethers.Contract( 15 | contractAddresses.WMNT, 16 | abi, 17 | accounts[0] 18 | ); 19 | 20 | let depositlTx = await wmntContract.deposit({ value: "100000000000000000000" }); 21 | console.log("deposit tx: ", depositlTx.hash); 22 | } 23 | 24 | // We recommend this pattern to be able to use async/await everywhere 25 | // and properly handle errors. 26 | main().catch((error) => { 27 | console.error(error); 28 | process.exitCode = 1; 29 | }); -------------------------------------------------------------------------------- /deployments/mantleSepoliaTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniPoolDeployer": "0x6C53C6cC7c10B389c5680458Fc0C4079f3F012b4", 3 | "AgniFactory": "0xA9AcD50B042A72c33d05fDcC8ad209d3aD361762", 4 | "InitCodeHashAddress": "0xa18655b73FDC38665CFB9e09A5a0a10C14e68EC5", 5 | "InitCodeHash": "0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a", 6 | "WMNT": "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF", 7 | "SwapRouter": "0xe38cfa32cCd918d94E2e20230dFaD1A4Fd8aEF16", 8 | "Quoter": "0xA82F8dC4704d3512b120de70480219761F24B6Eb", 9 | "QuoterV2": "0x9Da17239a4170f50A5A2c11813BD0C601b5c9693", 10 | "TickLens": "0xB4EB98c6d7D4807033Ae6195241ef7A839070748", 11 | "NFTDescriptor": "0x7C20eE7CC3230003401cC19BF076871Aedf39856", 12 | "NonfungibleTokenPositionDescriptor": "0x497bd1C86a1088e80f58EaA13de8C81aB70a4e79", 13 | "NonfungiblePositionManager": "0x71959543c31EC4d68D9D6C492Bf69A1C174bb394", 14 | "AgniInterfaceMulticall": "0x49b05721B9615dC1811E20F47D5700dA2d6Ed429", 15 | "Multicall3": "0x521751C88EafdCAEd9cAbb4dB35a1400D6933428" 16 | } 17 | -------------------------------------------------------------------------------- /core/contracts/interfaces/callback/IAgniMintCallback.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Callback for IAgniPoolActions#mint 5 | /// @notice Any contract that calls IAgniPoolActions#mint must implement this interface 6 | interface IAgniMintCallback { 7 | /// @notice Called to `msg.sender` after minting liquidity to a position from IAgniPool#mint. 8 | /// @dev In the implementation you must pay the pool tokens owed for the minted liquidity. 9 | /// The caller of this method must be checked to be a AgniPool deployed by the canonical AgniFactory. 10 | /// @param amount0Owed The amount of token0 due to the pool for the minted liquidity 11 | /// @param amount1Owed The amount of token1 due to the pool for the minted liquidity 12 | /// @param data Any data passed through by the caller via the IAgniPoolActions#mint call 13 | function agniMintCallback( 14 | uint256 amount0Owed, 15 | uint256 amount1Owed, 16 | bytes calldata data 17 | ) external; 18 | } 19 | -------------------------------------------------------------------------------- /periphery/test/shared/snapshotGasCost.ts: -------------------------------------------------------------------------------- 1 | import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider' 2 | import { expect } from './expect' 3 | import { Contract, BigNumber, ContractTransaction } from 'ethers' 4 | 5 | export default async function snapshotGasCost( 6 | x: 7 | | TransactionResponse 8 | | Promise 9 | | ContractTransaction 10 | | Promise 11 | | TransactionReceipt 12 | | Promise 13 | | BigNumber 14 | | Contract 15 | | Promise 16 | ): Promise { 17 | const resolved = await x 18 | if ('deployTransaction' in resolved) { 19 | const receipt = await resolved.deployTransaction.wait() 20 | expect(receipt.gasUsed.toNumber()).toMatchSnapshot() 21 | } else if ('wait' in resolved) { 22 | const waited = await resolved.wait() 23 | expect(waited.gasUsed.toNumber()).toMatchSnapshot() 24 | } else if (BigNumber.isBigNumber(resolved)) { 25 | expect(resolved.toNumber()).toMatchSnapshot() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/contracts/interfaces/callback/IAgniFlashCallback.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Callback for IAgniPoolActions#flash 5 | /// @notice Any contract that calls IAgniPoolActions#flash must implement this interface 6 | interface IAgniFlashCallback { 7 | /// @notice Called to `msg.sender` after transferring to the recipient from IAgniPool#flash. 8 | /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts. 9 | /// The caller of this method must be checked to be a AgniPool deployed by the canonical AgniFactory. 10 | /// @param fee0 The fee amount in token0 due to the pool by the end of the flash 11 | /// @param fee1 The fee amount in token1 due to the pool by the end of the flash 12 | /// @param data Any data passed through by the caller via the IAgniPoolActions#flash call 13 | function agniFlashCallback( 14 | uint256 fee0, 15 | uint256 fee1, 16 | bytes calldata data 17 | ) external; 18 | } 19 | -------------------------------------------------------------------------------- /core/contracts/test/TickMathEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/TickMath.sol'; 5 | 6 | contract TickMathEchidnaTest { 7 | // uniqueness and increasing order 8 | function checkGetSqrtRatioAtTickInvariants(int24 tick) external pure { 9 | uint160 ratio = TickMath.getSqrtRatioAtTick(tick); 10 | assert(TickMath.getSqrtRatioAtTick(tick - 1) < ratio && ratio < TickMath.getSqrtRatioAtTick(tick + 1)); 11 | assert(ratio >= TickMath.MIN_SQRT_RATIO); 12 | assert(ratio <= TickMath.MAX_SQRT_RATIO); 13 | } 14 | 15 | // the ratio is always between the returned tick and the returned tick+1 16 | function checkGetTickAtSqrtRatioInvariants(uint160 ratio) external pure { 17 | int24 tick = TickMath.getTickAtSqrtRatio(ratio); 18 | assert(ratio >= TickMath.getSqrtRatioAtTick(tick) && ratio < TickMath.getSqrtRatioAtTick(tick + 1)); 19 | assert(tick >= TickMath.MIN_TICK); 20 | assert(tick < TickMath.MAX_TICK); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /periphery/contracts/NonfungibleTokenPositionDescriptorOffChain.sol: -------------------------------------------------------------------------------- 1 | pragma solidity =0.7.6; 2 | pragma abicoder v2; 3 | 4 | import '@openzeppelin/contracts-upgradeable/proxy/Initializable.sol'; 5 | import '@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol'; 6 | 7 | import './interfaces/INonfungibleTokenPositionDescriptor.sol'; 8 | 9 | /// @title Describes NFT token positions 10 | contract NonfungibleTokenPositionDescriptorOffChain is INonfungibleTokenPositionDescriptor, Initializable { 11 | using StringsUpgradeable for uint256; 12 | 13 | string private _baseTokenURI; 14 | 15 | function initialize(string calldata baseTokenURI) external initializer { 16 | _baseTokenURI = baseTokenURI; 17 | } 18 | 19 | function tokenURI(INonfungiblePositionManager positionManager, uint256 tokenId) 20 | external 21 | view 22 | override 23 | returns (string memory) 24 | { 25 | return bytes(_baseTokenURI).length > 0 ? string(abi.encodePacked(_baseTokenURI, tokenId.toString())) : ""; 26 | } 27 | } -------------------------------------------------------------------------------- /periphery/test/shared/formatSqrtRatioX96.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from 'ethers' 2 | import Decimal from 'decimal.js' 3 | 4 | const TWO = BigNumber.from(2) 5 | const TEN = BigNumber.from(10) 6 | const FIVE_SIG_FIGS_POW = new Decimal(10).pow(5) 7 | 8 | export function formatSqrtRatioX96( 9 | sqrtRatioX96: BigNumber | number, 10 | decimalsToken0: number = 18, 11 | decimalsToken1: number = 18 12 | ): string { 13 | Decimal.set({ toExpPos: 9_999_999, toExpNeg: -9_999_999 }) 14 | 15 | let ratioNum = ((parseInt(sqrtRatioX96.toString()) / 2 ** 96) ** 2).toPrecision(5) 16 | let ratio = new Decimal(ratioNum.toString()) 17 | 18 | // adjust for decimals 19 | if (decimalsToken1 < decimalsToken0) { 20 | ratio = ratio.mul(TEN.pow(decimalsToken0 - decimalsToken1).toString()) 21 | } else if (decimalsToken0 < decimalsToken1) { 22 | ratio = ratio.div(TEN.pow(decimalsToken1 - decimalsToken0).toString()) 23 | } 24 | 25 | if (ratio.lessThan(FIVE_SIG_FIGS_POW)) { 26 | return ratio.toPrecision(5) 27 | } 28 | 29 | return ratio.toString() 30 | } 31 | -------------------------------------------------------------------------------- /core/contracts/libraries/TransferHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.6.0; 3 | 4 | import '../interfaces/IERC20Minimal.sol'; 5 | 6 | /// @title TransferHelper 7 | /// @notice Contains helper methods for interacting with ERC20 tokens that do not consistently return true/false 8 | library TransferHelper { 9 | /// @notice Transfers tokens from msg.sender to a recipient 10 | /// @dev Calls transfer on token contract, errors with TF if transfer fails 11 | /// @param token The contract address of the token which will be transferred 12 | /// @param to The recipient of the transfer 13 | /// @param value The value of the transfer 14 | function safeTransfer( 15 | address token, 16 | address to, 17 | uint256 value 18 | ) internal { 19 | (bool success, bytes memory data) = token.call( 20 | abi.encodeWithSelector(IERC20Minimal.transfer.selector, to, value) 21 | ); 22 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TF'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /periphery/contracts/test/PoolAddressTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/PoolAddress.sol'; 5 | 6 | contract PoolAddressTest { 7 | function POOL_INIT_CODE_HASH() external pure returns (bytes32) { 8 | return PoolAddress.POOL_INIT_CODE_HASH; 9 | } 10 | 11 | function computeAddress( 12 | address deployer, 13 | address token0, 14 | address token1, 15 | uint24 fee 16 | ) external pure returns (address) { 17 | return PoolAddress.computeAddress(deployer, PoolAddress.PoolKey({token0: token0, token1: token1, fee: fee})); 18 | } 19 | 20 | function getGasCostOfComputeAddress( 21 | address deployer, 22 | address token0, 23 | address token1, 24 | uint24 fee 25 | ) external view returns (uint256) { 26 | uint256 gasBefore = gasleft(); 27 | PoolAddress.computeAddress(deployer, PoolAddress.PoolKey({token0: token0, token1: token1, fee: fee})); 28 | return gasBefore - gasleft(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IERC20 { 5 | event Approval(address indexed owner, address indexed spender, uint256 value); 6 | event Transfer(address indexed from, address indexed to, uint256 value); 7 | 8 | function name() external view returns (string memory); 9 | 10 | function symbol() external view returns (string memory); 11 | 12 | function decimals() external view returns (uint8); 13 | 14 | function totalSupply() external view returns (uint256); 15 | 16 | function balanceOf(address owner) external view returns (uint256); 17 | 18 | function allowance(address owner, address spender) external view returns (uint256); 19 | 20 | function approve(address spender, uint256 value) external returns (bool); 21 | 22 | function transfer(address to, uint256 value) external returns (bool); 23 | 24 | function transferFrom( 25 | address from, 26 | address to, 27 | uint256 value 28 | ) external returns (bool); 29 | } 30 | -------------------------------------------------------------------------------- /core/contracts/test/TickEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/Tick.sol'; 5 | 6 | contract TickEchidnaTest { 7 | function checkTickSpacingToParametersInvariants(int24 tickSpacing) external pure { 8 | require(tickSpacing <= TickMath.MAX_TICK); 9 | require(tickSpacing > 0); 10 | 11 | int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing; 12 | int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing; 13 | 14 | uint128 maxLiquidityPerTick = Tick.tickSpacingToMaxLiquidityPerTick(tickSpacing); 15 | 16 | // symmetry around 0 tick 17 | assert(maxTick == -minTick); 18 | // positive max tick 19 | assert(maxTick > 0); 20 | // divisibility 21 | assert((maxTick - minTick) % tickSpacing == 0); 22 | 23 | uint256 numTicks = uint256((maxTick - minTick) / tickSpacing) + 1; 24 | // max liquidity at every tick is less than the cap 25 | assert(uint256(maxLiquidityPerTick) * numTicks <= type(uint128).max); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /periphery/contracts/base/Multicall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | import '../interfaces/IMulticall.sol'; 6 | 7 | /// @title Multicall 8 | /// @notice Enables calling multiple methods in a single call to the contract 9 | abstract contract Multicall is IMulticall { 10 | /// @inheritdoc IMulticall 11 | function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) { 12 | results = new bytes[](data.length); 13 | for (uint256 i = 0; i < data.length; i++) { 14 | (bool success, bytes memory result) = address(this).delegatecall(data[i]); 15 | 16 | if (!success) { 17 | // Next 5 lines from https://ethereum.stackexchange.com/a/83577 18 | if (result.length < 68) revert(); 19 | assembly { 20 | result := add(result, 0x04) 21 | } 22 | revert(abi.decode(result, (string))); 23 | } 24 | 25 | results[i] = result; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /launchpad/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/launchpad", 3 | "version": "1.0.0", 4 | "description": "Launchpad smart contracts for interacting with Agni Protocol", 5 | "license": "GPL-2.0-or-later", 6 | "scripts": { 7 | "deploy": "hardhat run scripts/deploy.ts --network", 8 | "create_pool": "hardhat run scripts/create_pool.ts --network", 9 | "verify": "hardhat run scripts/verify.ts --network", 10 | "add_staking_token": "hardhat run scripts/add_staking_token.ts --network", 11 | "stake": "hardhat run scripts/stake.ts --network" 12 | }, 13 | "devDependencies": { 14 | "@agniswap/core": "file:../core", 15 | "@agniswap/periphery": "file:../periphery", 16 | "@chainlink/contracts": "0.6.1", 17 | "@nomicfoundation/hardhat-toolbox": "^2.0.2", 18 | "@openzeppelin/contracts": "3.4.2-solc-0.7", 19 | "@openzeppelin/contracts-upgradeable": "3.4.2-solc-0.7", 20 | "@openzeppelin/hardhat-upgrades": "^1.22.1", 21 | "dotenv": "^16.0.3", 22 | "hardhat": "^2.14.0", 23 | "hardhat-contract-sizer": "^2.6.1", 24 | "hardhat-gas-reporter": "^1.0.9" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /multicall3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/multicall3", 3 | "version": "1.0.1", 4 | "description": "multicall3 smart contracts for interacting with Agni Protocol", 5 | "license": "GPL-2.0-or-later", 6 | "publishConfig": { 7 | "access": "public" 8 | }, 9 | "keywords": [ 10 | "agniswap", 11 | "multicall3" 12 | ], 13 | "files": [ 14 | "contracts" 15 | ], 16 | "engines": { 17 | "node": ">=10" 18 | }, 19 | "scripts": { 20 | "deploy": "hardhat run scripts/deploy.ts --network ", 21 | "verify": "hardhat run scripts/verify.ts --network" 22 | }, 23 | "devDependencies": { 24 | "@agniswap/core": "file:../core", 25 | "@nomicfoundation/hardhat-toolbox": "^2.0.2", 26 | "@openzeppelin/contracts": "3.4.2-solc-0.7", 27 | "@openzeppelin/contracts-upgradeable": "3.4.2-solc-0.7", 28 | "@openzeppelin/hardhat-upgrades": "^1.22.1", 29 | "@uniswap/lib": "4.0.1-alpha", 30 | "base64-sol": "1.1.0", 31 | "dotenv": "^16.0.3", 32 | "hardhat": "^2.14.0", 33 | "hardhat-contract-sizer": "^2.6.1", 34 | "hardhat-gas-reporter": "^1.0.9" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /farmbooster/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/farmbooster", 3 | "version": "1.0.1", 4 | "description": "farmbooster smart contracts for interacting with Agni Protocol", 5 | "license": "GPL-2.0-or-later", 6 | "publishConfig": { 7 | "access": "public" 8 | }, 9 | "keywords": [ 10 | "agniswap", 11 | "farmbooster" 12 | ], 13 | "files": [ 14 | "contracts" 15 | ], 16 | "engines": { 17 | "node": ">=10" 18 | }, 19 | "scripts": { 20 | "deploy": "hardhat run scripts/deploy.ts --network ", 21 | "verify": "hardhat run scripts/verify.ts --network" 22 | }, 23 | "devDependencies": { 24 | "@agniswap/core": "file:../core", 25 | "@nomicfoundation/hardhat-toolbox": "^2.0.2", 26 | "@openzeppelin/contracts": "3.4.2-solc-0.7", 27 | "@openzeppelin/contracts-upgradeable": "3.4.2-solc-0.7", 28 | "@openzeppelin/hardhat-upgrades": "^1.22.1", 29 | "@uniswap/lib": "4.0.1-alpha", 30 | "base64-sol": "1.1.0", 31 | "dotenv": "^16.0.3", 32 | "hardhat": "^2.14.0", 33 | "hardhat-contract-sizer": "^2.6.1", 34 | "hardhat-gas-reporter": "^1.0.9" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /core/contracts/test/MockTimeAgniPoolDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/IAgniPoolDeployer.sol'; 5 | 6 | import './MockTimeAgniPool.sol'; 7 | 8 | contract MockTimeAgniPoolDeployer is IAgniPoolDeployer { 9 | struct Parameters { 10 | address factory; 11 | address token0; 12 | address token1; 13 | uint24 fee; 14 | int24 tickSpacing; 15 | } 16 | 17 | Parameters public override parameters; 18 | 19 | event PoolDeployed(address pool); 20 | 21 | function deploy( 22 | address factory, 23 | address token0, 24 | address token1, 25 | uint24 fee, 26 | int24 tickSpacing 27 | ) external override returns (address pool) { 28 | parameters = Parameters({factory: factory, token0: token0, token1: token1, fee: fee, tickSpacing: tickSpacing}); 29 | pool = address( 30 | new MockTimeAgniPool{salt: keccak256(abi.encodePacked(token0, token1, fee, tickSpacing))}() 31 | ); 32 | emit PoolDeployed(pool); 33 | delete parameters; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /periphery/test/shared/computePoolAddress.ts: -------------------------------------------------------------------------------- 1 | import { bytecode } from '../../../core/artifacts/contracts/AgniPool.sol/AgniPool.json' 2 | import { utils } from 'ethers' 3 | 4 | export const POOL_BYTECODE_HASH = utils.keccak256(bytecode) 5 | 6 | export function computePoolAddress(deployerAddress: string, [tokenA, tokenB]: [string, string], fee: number): string { 7 | console.log("POOL_BYTECODE_HASH", POOL_BYTECODE_HASH); 8 | const [token0, token1] = tokenA.toLowerCase() < tokenB.toLowerCase() ? [tokenA, tokenB] : [tokenB, tokenA] 9 | const constructorArgumentsEncoded = utils.defaultAbiCoder.encode( 10 | ['address', 'address', 'uint24'], 11 | [token0, token1, fee] 12 | ) 13 | 14 | const create2Inputs = [ 15 | "0xff", 16 | deployerAddress, 17 | // salt 18 | utils.keccak256(constructorArgumentsEncoded), 19 | // init code hash 20 | POOL_BYTECODE_HASH, 21 | // "0x6381d1fec6fd43bf99593bd7b0430ecc17a9539602121d21935e75216355d19c", 22 | ]; 23 | const sanitizedInputs = `0x${create2Inputs.map((i) => i.slice(2)).join('')}` 24 | return utils.getAddress(`0x${utils.keccak256(sanitizedInputs).slice(-40)}`) 25 | } 26 | -------------------------------------------------------------------------------- /periphery/contracts/test/PathTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/Path.sol'; 5 | 6 | contract PathTest { 7 | function hasMultiplePools(bytes memory path) public pure returns (bool) { 8 | return Path.hasMultiplePools(path); 9 | } 10 | 11 | function decodeFirstPool(bytes memory path) 12 | public 13 | pure 14 | returns ( 15 | address tokenA, 16 | address tokenB, 17 | uint24 fee 18 | ) 19 | { 20 | return Path.decodeFirstPool(path); 21 | } 22 | 23 | function getFirstPool(bytes memory path) public pure returns (bytes memory) { 24 | return Path.getFirstPool(path); 25 | } 26 | 27 | function skipToken(bytes memory path) public pure returns (bytes memory) { 28 | return Path.skipToken(path); 29 | } 30 | 31 | // gas funcs 32 | function getGasCostOfDecodeFirstPool(bytes memory path) public view returns (uint256) { 33 | uint256 gasBefore = gasleft(); 34 | Path.decodeFirstPool(path); 35 | return gasBefore - gasleft(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/contracts/test/SwapMathTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/SwapMath.sol'; 5 | 6 | contract SwapMathTest { 7 | function computeSwapStep( 8 | uint160 sqrtP, 9 | uint160 sqrtPTarget, 10 | uint128 liquidity, 11 | int256 amountRemaining, 12 | uint24 feePips 13 | ) 14 | external 15 | pure 16 | returns ( 17 | uint160 sqrtQ, 18 | uint256 amountIn, 19 | uint256 amountOut, 20 | uint256 feeAmount 21 | ) 22 | { 23 | return SwapMath.computeSwapStep(sqrtP, sqrtPTarget, liquidity, amountRemaining, feePips); 24 | } 25 | 26 | function getGasCostOfComputeSwapStep( 27 | uint160 sqrtP, 28 | uint160 sqrtPTarget, 29 | uint128 liquidity, 30 | int256 amountRemaining, 31 | uint24 feePips 32 | ) external view returns (uint256) { 33 | uint256 gasBefore = gasleft(); 34 | SwapMath.computeSwapStep(sqrtP, sqrtPTarget, liquidity, amountRemaining, feePips); 35 | return gasBefore - gasleft(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/contracts/libraries/SafeCast.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Safe casting methods 5 | /// @notice Contains methods for safely casting between types 6 | library SafeCast { 7 | /// @notice Cast a uint256 to a uint160, revert on overflow 8 | /// @param y The uint256 to be downcasted 9 | /// @return z The downcasted integer, now type uint160 10 | function toUint160(uint256 y) internal pure returns (uint160 z) { 11 | require((z = uint160(y)) == y); 12 | } 13 | 14 | /// @notice Cast a int256 to a int128, revert on overflow or underflow 15 | /// @param y The int256 to be downcasted 16 | /// @return z The downcasted integer, now type int128 17 | function toInt128(int256 y) internal pure returns (int128 z) { 18 | require((z = int128(y)) == y); 19 | } 20 | 21 | /// @notice Cast a uint256 to a int256, revert on overflow 22 | /// @param y The uint256 to be casted 23 | /// @return z The casted integer, now type int256 24 | function toInt256(uint256 y) internal pure returns (int256 z) { 25 | require(y < 2**255); 26 | z = int256(y); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/ITickLens.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | pragma abicoder v2; 4 | 5 | /// @title Tick Lens 6 | /// @notice Provides functions for fetching chunks of tick data for a pool 7 | /// @dev This avoids the waterfall of fetching the tick bitmap, parsing the bitmap to know which ticks to fetch, and 8 | /// then sending additional multicalls to fetch the tick data 9 | interface ITickLens { 10 | struct PopulatedTick { 11 | int24 tick; 12 | int128 liquidityNet; 13 | uint128 liquidityGross; 14 | } 15 | 16 | /// @notice Get all the tick data for the populated ticks from a word of the tick bitmap of a pool 17 | /// @param pool The address of the pool for which to fetch populated tick data 18 | /// @param tickBitmapIndex The index of the word in the tick bitmap for which to parse the bitmap and 19 | /// fetch all the populated ticks 20 | /// @return populatedTicks An array of tick data for the given word in the tick bitmap 21 | function getPopulatedTicksInWord(address pool, int16 tickBitmapIndex) 22 | external 23 | view 24 | returns (PopulatedTick[] memory populatedTicks); 25 | } 26 | -------------------------------------------------------------------------------- /core/contracts/test/LowGasSafeMathEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/LowGasSafeMath.sol'; 5 | 6 | contract LowGasSafeMathEchidnaTest { 7 | function checkAdd(uint256 x, uint256 y) external pure { 8 | uint256 z = LowGasSafeMath.add(x, y); 9 | assert(z == x + y); 10 | assert(z >= x && z >= y); 11 | } 12 | 13 | function checkSub(uint256 x, uint256 y) external pure { 14 | uint256 z = LowGasSafeMath.sub(x, y); 15 | assert(z == x - y); 16 | assert(z <= x); 17 | } 18 | 19 | function checkMul(uint256 x, uint256 y) external pure { 20 | uint256 z = LowGasSafeMath.mul(x, y); 21 | assert(z == x * y); 22 | assert(x == 0 || y == 0 || (z >= x && z >= y)); 23 | } 24 | 25 | function checkAddi(int256 x, int256 y) external pure { 26 | int256 z = LowGasSafeMath.add(x, y); 27 | assert(z == x + y); 28 | assert(y < 0 ? z < x : z >= x); 29 | } 30 | 31 | function checkSubi(int256 x, int256 y) external pure { 32 | int256 z = LowGasSafeMath.sub(x, y); 33 | assert(z == x - y); 34 | assert(y < 0 ? z > x : z <= x); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /deploy.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zx 2 | // import 'zx/globals' 3 | 4 | import fs from 'fs-extra' 5 | 6 | const networks = { 7 | hardhat: 'hardhat', 8 | mantleTestnet: 'mantleTestnet', 9 | mantleMainnet: 'mantleMainnet', 10 | mantleSepoliaTestnet: 'mantleSepoliaTestnet', 11 | } 12 | 13 | let network = "mantleMainnet" 14 | console.log(network, 'network') 15 | if (!network || !networks[network]) { 16 | throw new Error(`env NETWORK: ${network}`) 17 | } 18 | 19 | const c = await fs.readJson(`./core/deployments/${network}.json`) 20 | const p = await fs.readJson(`./periphery/deployments/${network}.json`) 21 | // const m = await fs.readJson(`./masterchef/deployments/${network}.json`) 22 | // const l = await fs.readJson(`./lm-pool/deployments/${network}.json`) 23 | // const la = await fs.readJson(`./launchpad/deployments/${network}.json`) 24 | const mu = await fs.readJson(`./multicall3/deployments/${network}.json`) 25 | 26 | const addresses = { 27 | ...c, 28 | ...p, 29 | // ...m, 30 | // ...l, 31 | // ...la, 32 | ...mu, 33 | } 34 | 35 | // console.log(chalk.blue('Writing to file...')) 36 | // console.log(chalk.yellow(JSON.stringify(addresses, null, 2))) 37 | 38 | fs.writeJson(`./deployments/${network}.json`, addresses, { spaces: 2 }) 39 | -------------------------------------------------------------------------------- /deployments/mantleMainnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniPoolDeployer": "0xe9827B4EBeB9AE41FC57efDdDd79EDddC2EA4d03", 3 | "AgniFactory": "0x25780dc8Fc3cfBD75F33bFDAB65e969b603b2035", 4 | "InitCodeHashAddress": "0x5cfa0f1c4067C90a50B973e5F98CD265de5Df724", 5 | "InitCodeHash": "0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a", 6 | "WMNT": "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8", 7 | "SwapRouter": "0x319B69888b0d11cEC22caA5034e25FfFBDc88421", 8 | "Quoter": "0x9488C05a7b75a6FefdcAE4f11a33467bcBA60177", 9 | "QuoterV2": "0xc4aaDc921E1cdb66c5300Bc158a313292923C0cb", 10 | "TickLens": "0xEcDbA665AA209247CD334d0D037B913528a7bf67", 11 | "NFTDescriptor": "0x70153a35c3005385b45c47cDcfc7197c1a22477a", 12 | "NonfungibleTokenPositionDescriptor": "0xcb814b767D41b4BD94dA6Abb860D25b607ad5764", 13 | "NonfungiblePositionManager": "0x218bf598D1453383e2F4AA7b14fFB9BfB102D637", 14 | "AgniInterfaceMulticall": "0xBE592EFcF174b3E0E4208DC8c1658822d017568f", 15 | "mixedRouteQuoterV1": "0xcdbd1c6cfc89Af8a518E23B0C71996B90a12Befc", 16 | "smartRouterHelper": "0xb0Bcbe0d2B197b7a8Fb7e66d6a0dD6a91cB985d6", 17 | "smartRouter": "0xB52b1F5e08c04a8c33F4C7363fa2DE23B9BC169f", 18 | "Multicall3": "0x05f3105fc9FC531712b2570f1C6E11dD4bCf7B3c" 19 | } 20 | -------------------------------------------------------------------------------- /core/contracts/test/TickMathTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/TickMath.sol'; 5 | 6 | contract TickMathTest { 7 | function getSqrtRatioAtTick(int24 tick) external pure returns (uint160) { 8 | return TickMath.getSqrtRatioAtTick(tick); 9 | } 10 | 11 | function getGasCostOfGetSqrtRatioAtTick(int24 tick) external view returns (uint256) { 12 | uint256 gasBefore = gasleft(); 13 | TickMath.getSqrtRatioAtTick(tick); 14 | return gasBefore - gasleft(); 15 | } 16 | 17 | function getTickAtSqrtRatio(uint160 sqrtPriceX96) external pure returns (int24) { 18 | return TickMath.getTickAtSqrtRatio(sqrtPriceX96); 19 | } 20 | 21 | function getGasCostOfGetTickAtSqrtRatio(uint160 sqrtPriceX96) external view returns (uint256) { 22 | uint256 gasBefore = gasleft(); 23 | TickMath.getTickAtSqrtRatio(sqrtPriceX96); 24 | return gasBefore - gasleft(); 25 | } 26 | 27 | function MIN_SQRT_RATIO() external pure returns (uint160) { 28 | return TickMath.MIN_SQRT_RATIO; 29 | } 30 | 31 | function MAX_SQRT_RATIO() external pure returns (uint160) { 32 | return TickMath.MAX_SQRT_RATIO; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IPoolInitializer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | pragma abicoder v2; 4 | 5 | /// @title Creates and initializes V3 Pools 6 | /// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that 7 | /// require the pool to exist. 8 | interface IPoolInitializer { 9 | /// @notice Creates a new pool if it does not exist, then initializes if not initialized 10 | /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool 11 | /// @param token0 The contract address of token0 of the pool 12 | /// @param token1 The contract address of token1 of the pool 13 | /// @param fee The fee amount of the v3 pool for the specified token pair 14 | /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value 15 | /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary 16 | function createAndInitializePoolIfNecessary( 17 | address token0, 18 | address token1, 19 | uint24 fee, 20 | uint160 sqrtPriceX96 21 | ) external payable returns (address pool); 22 | } 23 | -------------------------------------------------------------------------------- /periphery/contracts/base/PoolInitializer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '@agniswap/core/contracts/interfaces/IAgniFactory.sol'; 5 | import '@agniswap/core/contracts/interfaces/IAgniPool.sol'; 6 | 7 | import './PeripheryImmutableState.sol'; 8 | import '../interfaces/IPoolInitializer.sol'; 9 | 10 | /// @title Creates and initializes V3 Pools 11 | abstract contract PoolInitializer is IPoolInitializer, PeripheryImmutableState { 12 | /// @inheritdoc IPoolInitializer 13 | function createAndInitializePoolIfNecessary( 14 | address token0, 15 | address token1, 16 | uint24 fee, 17 | uint160 sqrtPriceX96 18 | ) external payable override returns (address pool) { 19 | require(token0 < token1); 20 | pool = IAgniFactory(factory).getPool(token0, token1, fee); 21 | 22 | if (pool == address(0)) { 23 | pool = IAgniFactory(factory).createPool(token0, token1, fee); 24 | IAgniPool(pool).initialize(sqrtPriceX96); 25 | } else { 26 | (uint160 sqrtPriceX96Existing, , , , , , ) = IAgniPool(pool).slot0(); 27 | if (sqrtPriceX96Existing == 0) { 28 | IAgniPool(pool).initialize(sqrtPriceX96); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/README.md: -------------------------------------------------------------------------------- 1 | # Agni Core 2 | 3 | This repository contains the core smart contracts for the Agni Protocol. 4 | For higher level contracts, see the [periphery](../periphery/) 5 | repository. 6 | 7 | ## Local deployment 8 | 9 | In order to deploy this code to a local testnet, you should install the npm package 10 | `@agniswap/core` 11 | and import the factory bytecode located at 12 | `@agniswap/core/artifacts/contracts/AgniFactory.sol/AgniFactory.json`. 13 | For example: 14 | 15 | ```typescript 16 | import { 17 | abi as FACTORY_ABI, 18 | bytecode as FACTORY_BYTECODE, 19 | } from "@agniswap/core/artifacts/contracts/AgniFactory.sol/AgniFactory.json"; 20 | 21 | // deploy the bytecode 22 | ``` 23 | 24 | This will ensure that you are testing against the same bytecode that is deployed to 25 | mainnet and public testnets, and all PancakeSwap code will correctly interoperate with 26 | your local deployment. 27 | 28 | ## Using solidity interfaces 29 | 30 | The PancakeSwap v3 interfaces are available for import into solidity smart contracts 31 | via the npm artifact `@agniswap/core`, e.g.: 32 | 33 | ```solidity 34 | import '@agniswap/core/contracts/interfaces/IAgniPool.sol'; 35 | 36 | contract MyContract { 37 | IAgniPool pool; 38 | 39 | function doSomethingWithPool() { 40 | // pool.swap(...); 41 | } 42 | } 43 | 44 | ``` 45 | -------------------------------------------------------------------------------- /lm-pool/contracts/AgniLmPoolDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '@agniswap/core/contracts/interfaces/IAgniFactory.sol'; 5 | import '@agniswap/periphery/contracts/interfaces/INonfungiblePositionManager.sol'; 6 | 7 | import './AgniLmPool.sol'; 8 | 9 | /// @dev This contract is for Master Chef to create a corresponding LmPool when 10 | /// adding a new farming pool. As for why not just create LmPool inside the 11 | /// Master Chef contract is merely due to the imcompatibility of the solidity 12 | /// versions. 13 | contract AgniLmPoolDeployer { 14 | address public immutable masterChef; 15 | 16 | modifier onlyMasterChef() { 17 | require(msg.sender == masterChef, "Not MC"); 18 | _; 19 | } 20 | 21 | constructor(address _masterChef) { 22 | masterChef = _masterChef; 23 | } 24 | 25 | /// @dev Deploys a LmPool 26 | /// @param pool The contract address of the Agni pool 27 | function deploy(IAgniPool pool) external onlyMasterChef returns (IAgniLmPool lmPool) { 28 | lmPool = new AgniLmPool(address(pool), masterChef, uint32(block.timestamp)); 29 | IAgniFactory(INonfungiblePositionManager(IMasterChefV3(masterChef).nonfungiblePositionManager()).factory()).setLmPool(address(pool), address(lmPool)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IPeripheryPaymentsWithFee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | 4 | import './IPeripheryPayments.sol'; 5 | 6 | /// @title Periphery Payments 7 | /// @notice Functions to ease deposits and withdrawals of MNT 8 | interface IPeripheryPaymentsWithFee is IPeripheryPayments { 9 | /// @notice Unwraps the contract's WMNT balance and sends it to recipient as MNT, with a percentage between 10 | /// 0 (exclusive), and 1 (inclusive) going to feeRecipient 11 | /// @dev The amountMinimum parameter prevents malicious contracts from stealing WMNT from users. 12 | function unwrapWMNTWithFee( 13 | uint256 amountMinimum, 14 | address recipient, 15 | uint256 feeBips, 16 | address feeRecipient 17 | ) external payable; 18 | 19 | /// @notice Transfers the full amount of a token held by this contract to recipient, with a percentage between 20 | /// 0 (exclusive) and 1 (inclusive) going to feeRecipient 21 | /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users 22 | function sweepTokenWithFee( 23 | address token, 24 | uint256 amountMinimum, 25 | address recipient, 26 | uint256 feeBips, 27 | address feeRecipient 28 | ) external payable; 29 | } 30 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/external/IERC20PermitAllowed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Interface for permit 5 | /// @notice Interface used by DAI/CHAI for permit 6 | interface IERC20PermitAllowed { 7 | /// @notice Approve the spender to spend some tokens via the holder signature 8 | /// @dev This is the permit interface used by DAI and CHAI 9 | /// @param holder The address of the token holder, the token owner 10 | /// @param spender The address of the token spender 11 | /// @param nonce The holder's nonce, increases at each call to permit 12 | /// @param expiry The timestamp at which the permit is no longer valid 13 | /// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0 14 | /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` 15 | /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` 16 | /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` 17 | function permit( 18 | address holder, 19 | address spender, 20 | uint256 nonce, 21 | uint256 expiry, 22 | bool allowed, 23 | uint8 v, 24 | bytes32 r, 25 | bytes32 s 26 | ) external; 27 | } 28 | -------------------------------------------------------------------------------- /periphery/contracts/libraries/HexStrings.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity =0.7.6; 3 | 4 | library HexStrings { 5 | bytes16 internal constant ALPHABET = '0123456789abcdef'; 6 | 7 | /// @notice Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. 8 | /// @dev Credit to Open Zeppelin under MIT license https://github.com/OpenZeppelin/openzeppelin-contracts/blob/243adff49ce1700e0ecb99fe522fb16cff1d1ddc/contracts/utils/Strings.sol#L55 9 | function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { 10 | bytes memory buffer = new bytes(2 * length + 2); 11 | buffer[0] = '0'; 12 | buffer[1] = 'x'; 13 | for (uint256 i = 2 * length + 1; i > 1; --i) { 14 | buffer[i] = ALPHABET[value & 0xf]; 15 | value >>= 4; 16 | } 17 | require(value == 0, 'Strings: hex length insufficient'); 18 | return string(buffer); 19 | } 20 | 21 | function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) { 22 | bytes memory buffer = new bytes(2 * length); 23 | for (uint256 i = buffer.length; i > 0; i--) { 24 | buffer[i - 1] = ALPHABET[value & 0xf]; 25 | value >>= 4; 26 | } 27 | return string(buffer); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /core/contracts/test/TestAgniSwapPay.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/IERC20Minimal.sol'; 5 | 6 | import '../interfaces/callback/IAgniSwapCallback.sol'; 7 | import '../interfaces/IAgniPool.sol'; 8 | 9 | contract TestAgniSwapPay is IAgniSwapCallback { 10 | function swap( 11 | address pool, 12 | address recipient, 13 | bool zeroForOne, 14 | uint160 sqrtPriceX96, 15 | int256 amountSpecified, 16 | uint256 pay0, 17 | uint256 pay1 18 | ) external { 19 | IAgniPool(pool).swap( 20 | recipient, 21 | zeroForOne, 22 | amountSpecified, 23 | sqrtPriceX96, 24 | abi.encode(msg.sender, pay0, pay1) 25 | ); 26 | } 27 | 28 | function agniSwapCallback( 29 | int256, 30 | int256, 31 | bytes calldata data 32 | ) external override { 33 | (address sender, uint256 pay0, uint256 pay1) = abi.decode(data, (address, uint256, uint256)); 34 | 35 | if (pay0 > 0) { 36 | IERC20Minimal(IAgniPool(msg.sender).token0()).transferFrom(sender, msg.sender, uint256(pay0)); 37 | } else if (pay1 > 0) { 38 | IERC20Minimal(IAgniPool(msg.sender).token1()).transferFrom(sender, msg.sender, uint256(pay1)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/contracts/interfaces/callback/IAgniSwapCallback.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Callback for IAgniPoolActions#swap 5 | /// @notice Any contract that calls IAgniPoolActions#swap must implement this interface 6 | interface IAgniSwapCallback { 7 | /// @notice Called to `msg.sender` after executing a swap via IAgniPool#swap. 8 | /// @dev In the implementation you must pay the pool tokens owed for the swap. 9 | /// The caller of this method must be checked to be a AgniPool deployed by the canonical AgniFactory. 10 | /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. 11 | /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by 12 | /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. 13 | /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by 14 | /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. 15 | /// @param data Any data passed through by the caller via the IAgniPoolActions#swap call 16 | function agniSwapCallback( 17 | int256 amount0Delta, 18 | int256 amount1Delta, 19 | bytes calldata data 20 | ) external; 21 | } 22 | -------------------------------------------------------------------------------- /periphery/README.md: -------------------------------------------------------------------------------- 1 | # Agni Periphery 2 | 3 | This repository contains the periphery smart contracts for the Agni Protocol. 4 | For the lower level core contracts, see the [core](../core/) 5 | repository. 6 | 7 | ## Local deployment 8 | 9 | In order to deploy this code to a local testnet, you should install the npm package 10 | `@agniswap/periphery` 11 | and import bytecode imported from artifacts located at 12 | `@agniswap/periphery/artifacts/contracts/*/*.json`. 13 | For example: 14 | 15 | ```typescript 16 | import { 17 | abi as SWAP_ROUTER_ABI, 18 | bytecode as SWAP_ROUTER_BYTECODE, 19 | } from "@agniswap/periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json"; 20 | 21 | // deploy the bytecode 22 | ``` 23 | 24 | This will ensure that you are testing against the same bytecode that is deployed to 25 | mainnet and public testnets, and all Agni code will correctly interoperate with 26 | your local deployment. 27 | 28 | ## Using solidity interfaces 29 | 30 | The Agni periphery interfaces are available for import into solidity smart contracts 31 | via the npm artifact `@agniswap/periphery`, e.g.: 32 | 33 | ```solidity 34 | import '@agniswap/periphery/contracts/interfaces/ISwapRouter.sol'; 35 | 36 | contract MyContract { 37 | ISwapRouter router; 38 | 39 | function doSomethingWithSwapRouter() { 40 | // router.exactInput(...); 41 | } 42 | } 43 | 44 | ``` 45 | -------------------------------------------------------------------------------- /periphery/test/shared/formatSqrtRatioX96.spec.ts: -------------------------------------------------------------------------------- 1 | import { encodePriceSqrt } from './encodePriceSqrt' 2 | import { expect } from './expect' 3 | import { formatSqrtRatioX96 } from './formatSqrtRatioX96' 4 | 5 | describe('#formatSqrtRatioX96', () => { 6 | it('is correct for 9_999_999/10_000_000', () => { 7 | expect(formatSqrtRatioX96(encodePriceSqrt(9_999_999, 10_000_000))).to.eq('1.0000') 8 | }) 9 | it('is correct for 9_999_999/1', () => { 10 | expect(formatSqrtRatioX96(encodePriceSqrt(9_999_999, 1))).to.eq('10000000') 11 | }) 12 | it('is correct for 1/3', () => { 13 | expect(formatSqrtRatioX96(encodePriceSqrt(1, 3))).to.eq('0.33333') 14 | }) 15 | it('is correct for 100/3', () => { 16 | expect(formatSqrtRatioX96(encodePriceSqrt(100, 3))).to.eq('33.333') 17 | }) 18 | it('is correct for 1_000_000/3', () => { 19 | expect(formatSqrtRatioX96(encodePriceSqrt(1_000_000, 3))).to.eq('333330') 20 | }) 21 | it('1e-18 still prints 5 sig figs', () => { 22 | expect(formatSqrtRatioX96(encodePriceSqrt(1, 1e18), 18, 18)).to.eq('0.0000000000000000010000') 23 | }) 24 | it('accounts for decimal differences', () => { 25 | expect(formatSqrtRatioX96(encodePriceSqrt(1e6, 1e18), 18, 6)).to.eq('1.0000') 26 | }) 27 | it('accounts for decimal differences in reverse', () => { 28 | expect(formatSqrtRatioX96(encodePriceSqrt(1e18, 1e6), 6, 18)).to.eq('1.0000') 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /farmbooster/contracts/libraries/IterateMapping.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.9; 3 | 4 | struct ItMap { 5 | // pid => boost 6 | mapping(uint256 => uint256) data; 7 | // pid => index 8 | mapping(uint256 => uint256) indexs; 9 | // array of pid 10 | uint256[] keys; 11 | // never use it, just for keep compile success. 12 | uint256 size; 13 | } 14 | 15 | library IterableMapping { 16 | function insert(ItMap storage self, uint256 key, uint256 value) internal { 17 | uint256 keyIndex = self.indexs[key]; 18 | self.data[key] = value; 19 | if (keyIndex > 0) return; 20 | else { 21 | self.indexs[key] = self.keys.length + 1; 22 | self.keys.push(key); 23 | return; 24 | } 25 | } 26 | 27 | function remove(ItMap storage self, uint256 key) internal { 28 | uint256 index = self.indexs[key]; 29 | if (index == 0) return; 30 | uint256 lastKey = self.keys[self.keys.length - 1]; 31 | if (key != lastKey) { 32 | self.keys[index - 1] = lastKey; 33 | self.indexs[lastKey] = index; 34 | } 35 | delete self.data[key]; 36 | delete self.indexs[key]; 37 | self.keys.pop(); 38 | } 39 | 40 | function contains(ItMap storage self, uint256 key) internal view returns (bool) { 41 | return self.indexs[key] > 0; 42 | } 43 | } -------------------------------------------------------------------------------- /lm-pool/scripts/verify.ts: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const {network} = require("hardhat"); 3 | const utils = require("../../common/utils"); 4 | 5 | let WMNT=""; 6 | let AGNI=""; 7 | 8 | 9 | async function main() { 10 | const networkName = await network.name; 11 | console.log("Network name=", networkName); 12 | if (networkName == "mantleMainnet") { 13 | WMNT = "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"; 14 | AGNI = ""; 15 | } else { 16 | WMNT = "0xEa12Be2389c2254bAaD383c6eD1fa1e15202b52A"; 17 | AGNI = "0x113667C49c053230D3232AC7d74F471Dcd42f11E"; 18 | } 19 | console.log("WMNT addresses:", WMNT); 20 | 21 | 22 | let contractAddresses = utils.getContractAddresses(networkName,""); 23 | 24 | let masterChefContractAddresses = utils.getContractAddresses( 25 | networkName,`../masterChef/deployments/${process.env.NETWORK}.json` 26 | ); 27 | console.log("masterChef contract addresses:", masterChefContractAddresses); 28 | 29 | await hre.run("verify:verify", { 30 | address: contractAddresses.AgniLmPoolDeployer, 31 | contract: "contracts/AgniLmPoolDeployer.sol:AgniLmPoolDeployer", 32 | constructorArguments: [masterChefContractAddresses.MasterChef], 33 | }); 34 | } 35 | 36 | // We recommend this pattern to be able to use async/await everywhere 37 | // and properly handle errors. 38 | main().catch((error) => { 39 | console.error(error); 40 | process.exitCode = 1; 41 | }); 42 | -------------------------------------------------------------------------------- /core/contracts/interfaces/pool/IAgniPoolOwnerActions.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Permissioned pool actions 5 | /// @notice Contains pool methods that may only be called by the factory owner 6 | interface IAgniPoolOwnerActions { 7 | /// @notice Set the denominator of the protocol's % share of the fees 8 | /// @param feeProtocol0 new protocol fee for token0 of the pool 9 | /// @param feeProtocol1 new protocol fee for token1 of the pool 10 | function setFeeProtocol(uint32 feeProtocol0, uint32 feeProtocol1) external; 11 | 12 | /// @notice Collect the protocol fee accrued to the pool 13 | /// @param recipient The address to which collected protocol fees should be sent 14 | /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1 15 | /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0 16 | /// @return amount0 The protocol fee collected in token0 17 | /// @return amount1 The protocol fee collected in token1 18 | function collectProtocol( 19 | address recipient, 20 | uint128 amount0Requested, 21 | uint128 amount1Requested 22 | ) external returns (uint128 amount0, uint128 amount1); 23 | 24 | /// @notice Set the LM pool to enable liquidity mining 25 | function setLmPool(address lmPool) external; 26 | } 27 | -------------------------------------------------------------------------------- /masterchef/contracts/libraries/SafeCast.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.10; 4 | 5 | /** 6 | * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow 7 | * checks. 8 | * 9 | * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can 10 | * easily result in undesired exploitation or bugs, since developers usually 11 | * assume that overflows raise errors. `SafeCast` restores this intuition by 12 | * reverting the transaction when such an operation overflows. 13 | * 14 | * Using this library instead of the unchecked operations eliminates an entire 15 | * class of bugs, so it's recommended to use it always. 16 | * 17 | * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing 18 | * all math on `uint256` and `int256` and then downcasting. 19 | */ 20 | library SafeCast { 21 | /** 22 | * @dev Returns the downcasted uint128 from uint256, reverting on 23 | * overflow (when the input is greater than largest uint128). 24 | * 25 | * Counterpart to Solidity's `uint128` operator. 26 | * 27 | * Requirements: 28 | * 29 | * - input must fit into 128 bits 30 | */ 31 | function toUint128(uint256 value) internal pure returns (uint128) { 32 | require(value < 2 ** 128, "SafeCast: value doesn't fit in 128 bits"); 33 | return uint128(value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /masterchef/scripts/upkeep.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | 4 | async function main() { 5 | const networkName = await network.name; 6 | console.log("Network name=", networkName); 7 | 8 | let contractAddresses = utils.getContractAddresses(networkName, ""); 9 | 10 | const MasterChefV3Receiver = await ethers.getContractFactory( 11 | "MasterChefV3Receiver" 12 | ); 13 | const masterChefRecevier = await MasterChefV3Receiver.attach( 14 | contractAddresses.MasterChefV3Receiver 15 | ); 16 | 17 | let upkeepTx = await masterChefRecevier.upkeep( 18 | "10000000000000000000000", // 10000个rAgni 19 | 86400 * 30, 20 | true 21 | ); 22 | console.log("upkeep tx:", upkeepTx.hash); 23 | 24 | // incentive pool 25 | const IncentivePoolReceiver = await ethers.getContractFactory( 26 | "IncentivePoolReceiver" 27 | ); 28 | const extraIncentivePoolReceiver = await IncentivePoolReceiver.attach( 29 | contractAddresses.IncentivePoolReceiver 30 | ); 31 | 32 | upkeepTx = await extraIncentivePoolReceiver.upkeep( 33 | "100000000000000000000", // 100个WMNT 34 | 86400 * 30 35 | ); 36 | console.log("incentive pool upkeep tx:", upkeepTx.hash); 37 | } 38 | 39 | // We recommend this pattern to be able to use async/await everywhere 40 | // and properly handle errors. 41 | main().catch((error) => { 42 | console.error(error); 43 | process.exitCode = 1; 44 | }); 45 | -------------------------------------------------------------------------------- /v2-protocol/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/v2-core", 3 | "description": "Exchange contracts from Uniswap v2, and new features (zaps)", 4 | "version": "2.0.0", 5 | "license": "GPL-3.0/MIT", 6 | "private": true, 7 | "scripts": { 8 | "compile": "hardhat compile", 9 | "deploy": "hardhat run scripts/deploy.ts --network ", 10 | "verify": "hardhat run scripts/verify.ts --network ", 11 | "test:size-contracts": "hardhat size-contracts" 12 | }, 13 | "devDependencies": { 14 | "@uniswap/lib": "4.0.1-alpha", 15 | "@openzeppelin/contracts": "3.4.2-solc-0.7", 16 | "@nomicfoundation/hardhat-chai-matchers": "2.0.2", 17 | "@nomicfoundation/hardhat-ethers": "3.0.4", 18 | "@nomicfoundation/hardhat-network-helpers": "1.0.8", 19 | "@nomicfoundation/hardhat-toolbox": "3.0.0", 20 | "@nomicfoundation/hardhat-verify": "^1.1.1", 21 | "@typechain/ethers-v6": "0.5.0", 22 | "@typechain/hardhat": "9.0.0", 23 | "@types/chai": "4.3.5", 24 | "@types/mocha": "10.0.1", 25 | "@types/node": "20.5.6", 26 | "chai": "4.3.8", 27 | "dotenv": "^16.3.1", 28 | "ethers": "6.1.0", 29 | "hardhat": "2.22.18", 30 | "hardhat-contract-sizer": "^2.10.0", 31 | "hardhat-deploy": "0.11.37", 32 | "hardhat-deploy-ethers": "0.4.1", 33 | "hardhat-gas-reporter": "1.0.9", 34 | "solidity-coverage": "0.8.4", 35 | "ts-node": "10.9.1", 36 | "typechain": "8.3.1", 37 | "typescript": "5.2.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/contracts/test/TickBitmapTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/TickBitmap.sol'; 5 | 6 | contract TickBitmapTest { 7 | using TickBitmap for mapping(int16 => uint256); 8 | 9 | mapping(int16 => uint256) public bitmap; 10 | 11 | function flipTick(int24 tick) external { 12 | bitmap.flipTick(tick, 1); 13 | } 14 | 15 | function getGasCostOfFlipTick(int24 tick) external returns (uint256) { 16 | uint256 gasBefore = gasleft(); 17 | bitmap.flipTick(tick, 1); 18 | return gasBefore - gasleft(); 19 | } 20 | 21 | function nextInitializedTickWithinOneWord(int24 tick, bool lte) 22 | external 23 | view 24 | returns (int24 next, bool initialized) 25 | { 26 | return bitmap.nextInitializedTickWithinOneWord(tick, 1, lte); 27 | } 28 | 29 | function getGasCostOfNextInitializedTickWithinOneWord(int24 tick, bool lte) external view returns (uint256) { 30 | uint256 gasBefore = gasleft(); 31 | bitmap.nextInitializedTickWithinOneWord(tick, 1, lte); 32 | return gasBefore - gasleft(); 33 | } 34 | 35 | // returns whether the given tick is initialized 36 | function isInitialized(int24 tick) external view returns (bool) { 37 | (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(tick, 1, true); 38 | return next == tick ? initialized : false; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lm-pool/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/lm-pool", 3 | "version": "1.0.0", 4 | "description": "LiquidityMining Pool smart contracts for interacting with Agni Protocol", 5 | "license": "GPL-2.0-or-later", 6 | "scripts": { 7 | "deploy": "hardhat run scripts/deploy.ts --network", 8 | "verify": "hardhat run scripts/verify.ts --network" 9 | }, 10 | "devDependencies": { 11 | "@agniswap/core": "file:../core", 12 | "@chainlink/contracts": "0.6.1", 13 | "@nomicfoundation/hardhat-toolbox": "^2.0.2", 14 | "@openzeppelin/contracts": "^3.4.2-solc-0.7", 15 | "@openzeppelin/contracts-upgradeable": "3.4.2-solc-0.7", 16 | "@openzeppelin/hardhat-upgrades": "^1.22.1", 17 | "dotenv": "^16.0.3", 18 | "hardhat": "^2.14.0", 19 | "hardhat-contract-sizer": "^2.6.1", 20 | "hardhat-gas-reporter": "^1.0.9" 21 | }, 22 | "dependencies": { 23 | "@agniswap/periphery": "file:../periphery", 24 | "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", 25 | "@nomicfoundation/hardhat-network-helpers": "^1.0.0", 26 | "@nomiclabs/hardhat-ethers": "^2.0.0", 27 | "@nomiclabs/hardhat-etherscan": "^3.0.0", 28 | "@typechain/ethers-v5": "^10.1.0", 29 | "@typechain/hardhat": "^6.1.2", 30 | "@types/chai": "^4.2.0", 31 | "@types/mocha": ">=9.1.0", 32 | "solidity-coverage": "^0.8.1", 33 | "ts-node": "^10.9.1", 34 | "typechain": "^8.1.0", 35 | "typescript": "^5.1.3", 36 | "web3": "^4.0.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /core/scripts/verify.ts: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const {network} = require("hardhat"); 3 | const utils = require("../../common/utils"); 4 | 5 | async function main() { 6 | const networkName = await network.name; 7 | console.log("Network name=", networkName); 8 | 9 | let contractAddresses = utils.getContractAddresses(networkName,""); 10 | 11 | // await hre.run("verify:verify", { 12 | // address: contractAddresses.AgniPoolDeployer, 13 | // contract: "contracts/AgniPoolDeployer.sol:AgniPoolDeployer", 14 | // constructorArguments: [], 15 | // }); 16 | // 17 | // await hre.run("verify:verify", { 18 | // address: contractAddresses.AgniFactory, 19 | // contract: "contracts/AgniFactory.sol:AgniFactory", 20 | // constructorArguments: [contractAddresses.AgniPoolDeployer], 21 | // }); 22 | // 23 | // await hre.run("verify:verify", { 24 | // address: contractAddresses.InitCodeHashAddress, 25 | // contract: "contracts/test/OutputCodeHash.sol:OutputCodeHash", 26 | // constructorArguments: [], 27 | // }); 28 | 29 | await hre.run("verify:verify", { 30 | address: '0xe8A95b8ADf3f07C3BE5b851bb35146d0C9fDAdd8' , 31 | contract: "contracts/AgniPool.sol:AgniPool", 32 | constructorArguments: [], 33 | }); 34 | } 35 | 36 | // We recommend this pattern to be able to use async/await everywhere 37 | // and properly handle errors. 38 | main().catch((error) => { 39 | console.error(error); 40 | process.exitCode = 1; 41 | }); 42 | -------------------------------------------------------------------------------- /periphery/contracts/lens/AgniInterfaceMulticall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity =0.7.6; 3 | pragma abicoder v2; 4 | 5 | /// @notice A fork of Multicall2 specifically tailored for the Agni Interface 6 | contract AgniInterfaceMulticall { 7 | struct Call { 8 | address target; 9 | uint256 gasLimit; 10 | bytes callData; 11 | } 12 | 13 | struct Result { 14 | bool success; 15 | uint256 gasUsed; 16 | bytes returnData; 17 | } 18 | 19 | function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { 20 | timestamp = block.timestamp; 21 | } 22 | 23 | function getEthBalance(address addr) public view returns (uint256 balance) { 24 | balance = addr.balance; 25 | } 26 | 27 | function multicall(Call[] memory calls) public returns (uint256 blockNumber, Result[] memory returnData) { 28 | blockNumber = block.number; 29 | returnData = new Result[](calls.length); 30 | for (uint256 i = 0; i < calls.length; i++) { 31 | (address target, uint256 gasLimit, bytes memory callData) = 32 | (calls[i].target, calls[i].gasLimit, calls[i].callData); 33 | uint256 gasLeftBefore = gasleft(); 34 | (bool success, bytes memory ret) = target.call{gas: gasLimit}(callData); 35 | uint256 gasUsed = gasLeftBefore - gasleft(); 36 | returnData[i] = Result(success, gasUsed, ret); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /periphery/scripts/quoteV2.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | import { encodePath } from "../test/shared/path"; 4 | 5 | const agniAddress = "0x201eba5cc46d216ce6dc03f6a759e8e766e956ae"; 6 | 7 | enum FeeAmount { 8 | LOW = 500, 9 | MEDIUM = 2500, 10 | HIGH = 10000, 11 | } 12 | 13 | async function main() { 14 | const networkName = await network.name; 15 | console.log("Network name=", networkName); 16 | 17 | const [owner] = await ethers.getSigners(); 18 | let contractAddresses = utils.getContractAddresses(networkName,""); 19 | console.log("contractAddresses:", contractAddresses); 20 | 21 | const QuoterV2 = await ethers.getContractAt( 22 | "QuoterV2", 23 | contractAddresses.QuoterV2 24 | ); 25 | console.log("QuoterV2:", contractAddresses.QuoterV2); 26 | 27 | let wmntAddress = await QuoterV2.callStatic.WMNT(); 28 | console.log("wmntAddress:", wmntAddress); 29 | 30 | let path = encodePath([wmntAddress, agniAddress], [FeeAmount.LOW]); 31 | console.log("path:", path); 32 | 33 | let res = await QuoterV2.callStatic.quoteExactInput( 34 | encodePath([wmntAddress, agniAddress], [FeeAmount.LOW]), 35 | "100000000000000000" 36 | ); 37 | 38 | console.log(res); 39 | } 40 | 41 | // We recommend this pattern to be able to use async/await everywhere 42 | // and properly handle errors. 43 | main().catch((error) => { 44 | console.error(error); 45 | process.exitCode = 1; 46 | }); 47 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IAgniERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | interface IAgniERC20 { 5 | event Approval(address indexed owner, address indexed spender, uint256 value); 6 | event Transfer(address indexed from, address indexed to, uint256 value); 7 | 8 | function name() external pure returns (string memory); 9 | 10 | function symbol() external pure returns (string memory); 11 | 12 | function decimals() external pure returns (uint8); 13 | 14 | function totalSupply() external view returns (uint256); 15 | 16 | function balanceOf(address owner) external view returns (uint256); 17 | 18 | function allowance(address owner, address spender) external view returns (uint256); 19 | 20 | function approve(address spender, uint256 value) external returns (bool); 21 | 22 | function transfer(address to, uint256 value) external returns (bool); 23 | 24 | function transferFrom( 25 | address from, 26 | address to, 27 | uint256 value 28 | ) external returns (bool); 29 | 30 | function DOMAIN_SEPARATOR() external view returns (bytes32); 31 | 32 | function PERMIT_TYPEHASH() external pure returns (bytes32); 33 | 34 | function nonces(address owner) external view returns (uint256); 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 | -------------------------------------------------------------------------------- /masterchef/scripts/add_pool.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | 4 | // const LpAddress = "0xa9fe976c41bc8ce9cf89126bad9309adf1efb7e2"; // MAMA-USDT 5 | const LpAddress = "0x335bb4d6d8166860e9cab64bdd3cb2249c9a469b"; // MAMA-MNT 6 | 7 | async function main() { 8 | const networkName = await network.name; 9 | console.log("Network name=", networkName); 10 | 11 | let contractAddresses = utils.getContractAddresses(networkName, ""); 12 | 13 | const MasterChef = await ethers.getContractFactory("MasterChef"); 14 | const masterChef = await MasterChef.attach(contractAddresses.MasterChef); 15 | 16 | let owner = await masterChef.owner(); 17 | console.log("master chef owner:", owner); 18 | 19 | let LMPoolDeployer = await masterChef.LMPoolDeployer(); 20 | console.log("master chef lm deploy:", LMPoolDeployer); 21 | 22 | let addPoolTx = await masterChef.add(10000, LpAddress, true); 23 | console.log("add pool tx: ", addPoolTx.hash); 24 | 25 | // add incentive pool 26 | const IncentivePool = await ethers.getContractFactory("ExtraIncentivePool"); 27 | const incentivePool = await IncentivePool.attach( 28 | contractAddresses.ExtraIncentivePool 29 | ); 30 | addPoolTx = await incentivePool.add(LpAddress, 10000); 31 | console.log("add incentive add pool tx: ", addPoolTx.hash); 32 | } 33 | 34 | // We recommend this pattern to be able to use async/await everywhere 35 | // and properly handle errors. 36 | main().catch((error) => { 37 | console.error(error); 38 | process.exitCode = 1; 39 | }); -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IPeripheryPayments.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | 4 | /// @title Periphery Payments 5 | /// @notice Functions to ease deposits and withdrawals of MNT 6 | interface IPeripheryPayments { 7 | /// @notice Unwraps the contract's WMNT balance and sends it to recipient as MNT. 8 | /// @dev The amountMinimum parameter prevents malicious contracts from stealing WMNT from users. 9 | /// @param amountMinimum The minimum amount of WMNT to unwrap 10 | /// @param recipient The address receiving MNT 11 | function unwrapWMNT(uint256 amountMinimum, address recipient) external payable; 12 | 13 | /// @notice Refunds any MNT balance held by this contract to the `msg.sender` 14 | /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps 15 | /// that use ether for the input amount 16 | function refundMNT() external payable; 17 | 18 | /// @notice Transfers the full amount of a token held by this contract to recipient 19 | /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users 20 | /// @param token The contract address of the token which will be transferred to `recipient` 21 | /// @param amountMinimum The minimum amount of token required for a transfer 22 | /// @param recipient The destination address of the token 23 | function sweepToken( 24 | address token, 25 | uint256 amountMinimum, 26 | address recipient 27 | ) external payable; 28 | } 29 | -------------------------------------------------------------------------------- /v2-protocol/scripts/verify.ts: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const {network} = require("hardhat"); 3 | const utils = require("../../common/utils"); 4 | 5 | 6 | async function main() { 7 | const networkName = await network.name; 8 | console.log("Network name=", networkName); 9 | 10 | let contractAddresses = utils.getContractAddresses(networkName, ""); 11 | 12 | await hre.run("verify:verify", { 13 | address: contractAddresses.AgniFactory, 14 | contract: "contracts/AgniFactory.sol:AgniFactory", 15 | constructorArguments: [contractAddresses.AgniFeeSetter], 16 | }); 17 | 18 | await hre.run("verify:verify", { 19 | address: contractAddresses.AgniRouter, 20 | contract: "contracts/AgniRouter.sol:AgniRouter", 21 | constructorArguments: [ 22 | contractAddresses.AgniFactory, 23 | contractAddresses.WMNT, 24 | ], 25 | }); 26 | await hre.run("verify:verify", { 27 | address: "0xD14c2A2950eA3B7BAdD6bDDB18f7A7744Cd705Be", 28 | contract: "contracts/AgniPair.sol:AgniPair", 29 | constructorArguments: [], 30 | }); 31 | await hre.run("verify:verify", { 32 | address: "0x43925FFfaDe90C48FBd12384D5F4d4DA9C359fc4", 33 | contract: "contracts/AgniPair.sol:AgniPair", 34 | constructorArguments: [], 35 | }); 36 | } 37 | 38 | // We recommend this pattern to be able to use async/await everywhere 39 | // and properly handle errors. 40 | main().catch((error) => { 41 | console.error(error); 42 | process.exitCode = 1; 43 | }); 44 | -------------------------------------------------------------------------------- /periphery/contracts/libraries/CallbackValidation.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import '@agniswap/core/contracts/interfaces/IAgniPool.sol'; 5 | import './PoolAddress.sol'; 6 | 7 | /// @notice Provides validation for callbacks from Agni Pools 8 | library CallbackValidation { 9 | /// @notice Returns the address of a valid Agni Pool 10 | /// @param deployer The contract address of the Agni deployer 11 | /// @param tokenA The contract address of either token0 or token1 12 | /// @param tokenB The contract address of the other token 13 | /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip 14 | /// @return pool The V3 pool contract address 15 | function verifyCallback( 16 | address deployer, 17 | address tokenA, 18 | address tokenB, 19 | uint24 fee 20 | ) internal view returns (IAgniPool pool) { 21 | return verifyCallback(deployer, PoolAddress.getPoolKey(tokenA, tokenB, fee)); 22 | } 23 | 24 | /// @notice Returns the address of a valid Agni Pool 25 | /// @param deployer The contract address of the Agni deployer 26 | /// @param poolKey The identifying key of the V3 pool 27 | /// @return pool The V3 pool contract address 28 | function verifyCallback(address deployer, PoolAddress.PoolKey memory poolKey) 29 | internal 30 | view 31 | returns (IAgniPool pool) 32 | { 33 | pool = IAgniPool(PoolAddress.computeAddress(deployer, poolKey)); 34 | require(msg.sender == address(pool)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /periphery/contracts/interfaces/IERC721Permit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | 4 | import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; 5 | 6 | /// @title ERC721 with permit 7 | /// @notice Extension to ERC721 that includes a permit function for signature based approvals 8 | interface IERC721Permit is IERC721 { 9 | /// @notice The permit typehash used in the permit signature 10 | /// @return The typehash for the permit 11 | function PERMIT_TYPEHASH() external pure returns (bytes32); 12 | 13 | /// @notice The domain separator used in the permit signature 14 | /// @return The domain seperator used in encoding of permit signature 15 | function DOMAIN_SEPARATOR() external view returns (bytes32); 16 | 17 | /// @notice Approve of a specific token ID for spending by spender via signature 18 | /// @param spender The account that is being approved 19 | /// @param tokenId The ID of the token that is being approved for spending 20 | /// @param deadline The deadline timestamp by which the call must be mined for the approve to work 21 | /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` 22 | /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` 23 | /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` 24 | function permit( 25 | address spender, 26 | uint256 tokenId, 27 | uint256 deadline, 28 | uint8 v, 29 | bytes32 r, 30 | bytes32 s 31 | ) external payable; 32 | } 33 | -------------------------------------------------------------------------------- /core/contracts/interfaces/IAgniPoolDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title An interface for a contract that is capable of deploying Agni Pools 5 | /// @notice A contract that constructs a pool must implement this to pass arguments to the pool 6 | /// @dev This is used to avoid having constructor arguments in the pool contract, which results in the init code hash 7 | /// of the pool being constant allowing the CREATE2 address of the pool to be cheaply computed on-chain 8 | interface IAgniPoolDeployer { 9 | /// @notice Get the parameters to be used in constructing the pool, set transiently during pool creation. 10 | /// @dev Called by the pool constructor to fetch the parameters of the pool 11 | /// Returns factory The factory address 12 | /// Returns token0 The first token of the pool by address sort order 13 | /// Returns token1 The second token of the pool by address sort order 14 | /// Returns fee The fee collected upon every swap in the pool, denominated in hundredths of a bip 15 | /// Returns tickSpacing The minimum number of ticks between initialized ticks 16 | function parameters() 17 | external 18 | view 19 | returns ( 20 | address factory, 21 | address token0, 22 | address token1, 23 | uint24 fee, 24 | int24 tickSpacing 25 | ); 26 | 27 | function deploy( 28 | address factory, 29 | address token0, 30 | address token1, 31 | uint24 fee, 32 | int24 tickSpacing 33 | ) external returns (address pool); 34 | } 35 | -------------------------------------------------------------------------------- /periphery/scripts/deploy_slf.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { BigNumber } from "@ethersproject/bignumber"; 3 | 4 | async function main() { 5 | const [owner] = await ethers.getSigners(); 6 | 7 | const SelfSufficientERC20 = await ethers.getContractFactory( 8 | "SelfSufficientERC20" 9 | ); 10 | // const USDC = await SelfSufficientERC20.deploy(); 11 | // await USDC.initlialize("MockUSDC", "USDC", 6); 12 | // console.log("USDC", USDC.address); 13 | // await USDC.mint(owner.address, BigNumber.from("10000000000000000000000000")); 14 | // await USDC.mint( 15 | // "0xf172E28863C417AA71ac691A8bc02CdFc856daFA", 16 | // BigNumber.from("10000000000000000000000000") 17 | // ); 18 | 19 | // const AGNI = await SelfSufficientERC20.deploy(); 20 | // await AGNI.initlialize("MockAGNI", "AGNI", 18); 21 | // console.log("AGNI", AGNI.address); 22 | // await AGNI.mint(owner.address, BigNumber.from("10000000000000000000000000")); 23 | 24 | 25 | const rAGNI = await SelfSufficientERC20.deploy(); 26 | await rAGNI.initlialize("MockrAGNI", "rAGNI", 18); 27 | console.log("rAGNI", rAGNI.address); 28 | await rAGNI.mint( 29 | owner.address, 30 | BigNumber.from("10000000000000000000000000") 31 | ); 32 | 33 | // const TickMath = await ethers.getContractFactory("ExternalTickMath"); 34 | // const tickMath = await TickMath.deploy(); 35 | // console.log("TickMath", tickMath.address); 36 | } 37 | 38 | // We recommend this pattern to be able to use async/await everywhere 39 | // and properly handle errors. 40 | main().catch((error) => { 41 | console.error(error); 42 | process.exitCode = 1; 43 | }); 44 | -------------------------------------------------------------------------------- /core/contracts/test/AgniPoolSwapTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../interfaces/IERC20Minimal.sol'; 5 | 6 | import '../interfaces/callback/IAgniSwapCallback.sol'; 7 | import '../interfaces/IAgniPool.sol'; 8 | 9 | contract AgniPoolSwapTest is IAgniSwapCallback { 10 | int256 private _amount0Delta; 11 | int256 private _amount1Delta; 12 | 13 | function getSwapResult( 14 | address pool, 15 | bool zeroForOne, 16 | int256 amountSpecified, 17 | uint160 sqrtPriceLimitX96 18 | ) 19 | external 20 | returns ( 21 | int256 amount0Delta, 22 | int256 amount1Delta, 23 | uint160 nextSqrtRatio 24 | ) 25 | { 26 | (amount0Delta, amount1Delta) = IAgniPool(pool).swap( 27 | address(0), 28 | zeroForOne, 29 | amountSpecified, 30 | sqrtPriceLimitX96, 31 | abi.encode(msg.sender) 32 | ); 33 | 34 | (nextSqrtRatio, , , , , , ) = IAgniPool(pool).slot0(); 35 | } 36 | 37 | function agniSwapCallback( 38 | int256 amount0Delta, 39 | int256 amount1Delta, 40 | bytes calldata data 41 | ) external override { 42 | address sender = abi.decode(data, (address)); 43 | 44 | if (amount0Delta > 0) { 45 | IERC20Minimal(IAgniPool(msg.sender).token0()).transferFrom(sender, msg.sender, uint256(amount0Delta)); 46 | } else if (amount1Delta > 0) { 47 | IERC20Minimal(IAgniPool(msg.sender).token1()).transferFrom(sender, msg.sender, uint256(amount1Delta)); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/scripts/pool_address.ts: -------------------------------------------------------------------------------- 1 | import { ethers, network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | const Web3 = require("web3"); 4 | import PoolArtifact from "../artifacts/contracts/AgniPool.sol/AgniPool.json"; 5 | 6 | const token0 = "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE"; 7 | const token1 = "0x78c1b0c915c4faa5fffa6cabf0219da63d7f4cb8"; 8 | const fee = 500; 9 | 10 | async function main() { 11 | const networkName = await network.name; 12 | console.log("Network name=", networkName); 13 | 14 | // let contractAddresses = utils.getContractAddresses(networkName,""); 15 | // console.log("contractAddresses:", contractAddresses); 16 | 17 | // const AgniFactory = await ethers.getContractAt( 18 | // "AgniFactory", 19 | // contractAddresses.AgniFactory 20 | // ); 21 | // let poolAddress = await AgniFactory.getPool(token0, token1, fee); 22 | // console.log("getPool:", poolAddress); 23 | 24 | // const hash = ethers.utils.keccak256(PoolArtifact.bytecode); 25 | // console.log(hash); 26 | 27 | const AgniPool = await ethers.getContractAt( 28 | "AgniPool", 29 | "0x54169896d28dec0FFABE3B16f90f71323774949f" 30 | ); 31 | 32 | let slot0 = await AgniPool.slot0(); 33 | console.log("slot0:", slot0); 34 | 35 | let pfee = await AgniPool.protocolFees(); 36 | console.log("token0 fee:", Web3.utils.fromWei(pfee.token0, "ether")); 37 | console.log("token1 fee:", Web3.utils.fromWei(pfee.token1, "ether")); 38 | } 39 | 40 | // We recommend this pattern to be able to use async/await everywhere 41 | // and properly handle errors. 42 | main().catch((error) => { 43 | console.error(error); 44 | process.exitCode = 1; 45 | }); 46 | -------------------------------------------------------------------------------- /deployments/mantleTestnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "AgniPoolDeployer": "0x0B7e80F0e664ae80bbE0c56f7908ef14f5898b1d", 3 | "AgniFactory": "0x503Ca2ad7C9C70F4157d14CF94D3ef5Fa96D7032", 4 | "InitCodeHashAddress": "0xECeFAd547Dd6E5556065dF7797D9fC892B5EA864", 5 | "InitCodeHash": "0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a", 6 | "WMNT": "0xEa12Be2389c2254bAaD383c6eD1fa1e15202b52A", 7 | "SwapRouter": "0xe2DB835566F8677d6889ffFC4F3304e8Df5Fc1df", 8 | "QuoterV2": "0x49C8bb51C6bb791e8D6C31310cE0C14f68492991", 9 | "TickLens": "0x0DC832e8cA4a7E1CE073096709474A5422029DB3", 10 | "NFTDescriptor": "0x8002eb63E37728ddf15bd42Bf2607CBbBa714b3f", 11 | "NonfungibleTokenPositionDescriptor": "0xDc7E9B3E927f2880CEa359e659321F9d232aCb2c", 12 | "NonfungiblePositionManager": "0xb04a19EF7853c52EDe6FBb28F8FfBecb73329eD7", 13 | "AgniInterfaceMulticall": "0xF9Ae3Cc6D6483722b94d7075C9B366bcbbbab9d3", 14 | "MasterChef": "0x0BC31D78e06ef928658e0B6AB50460552f3D91c4", 15 | "MasterChefV3Receiver": "0x882a2c07Bf04DEcCA36Be060B07d8BC0EE50D2Ff", 16 | "AgniLmPoolDeployer": "0x8e8a453Bc0d968bBb284766aa4fE018a367E3106", 17 | "ScoreCalculator": { 18 | "Proxy": "0x9Cecf546DC36A2DaA5eC7375C3cF35FEd1ADD7a2", 19 | "Admin": "0x077e4C7F653FFe83cb560d994aDFF5685b3F0e6B", 20 | "Implementation": "0xF3FaF04d1FeF0bce0a3cCD7a817810B9071fDa36" 21 | }, 22 | "StakingPool": "0x31Fa04284049BD9C3Aff46503482270f0Be4BC5E", 23 | "IdoPoolTemplate": "0xae411e11D9fA2773CEaC200cC2C73F17324Fc93B", 24 | "IdoPoolFactory": "0xBfdb61b73Ad4647f3EcBeeeE5e875F081C486d53", 25 | "InsurancePool": "0xccc6A1C40BCFd5458CE3ebB731644fc62E3041e9", 26 | "Multicall3": "0x70f0c400171158c29B61a3E79C92c72e95679541" 27 | } 28 | -------------------------------------------------------------------------------- /masterchef/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/masterchef", 3 | "version": "1.0.0", 4 | "description": "LiquidityMining MasterChef smart contracts for interacting with Agni Protocol", 5 | "license": "GPL-2.0-or-later", 6 | "scripts": { 7 | "deploy": "hardhat run scripts/deploy.ts --network", 8 | "set_lmpool_deployer": "hardhat run scripts/set_lm_deployer.ts --network", 9 | "add_pool": "hardhat run scripts/add_pool.ts --network", 10 | "upkeep": "hardhat run scripts/upkeep.ts --network", 11 | "verify": "hardhat run scripts/verify.ts --network", 12 | "deposit_wmnt": "hardhat run scripts/deposit_wmnt.ts --network" 13 | }, 14 | "devDependencies": { 15 | "@agniswap/core": "file:../core", 16 | "@chainlink/contracts": "0.6.1", 17 | "@nomicfoundation/hardhat-toolbox": "^2.0.2", 18 | "@openzeppelin/contracts": "^4.9.1", 19 | "@openzeppelin/contracts-upgradeable": "^4.8.3", 20 | "@openzeppelin/hardhat-upgrades": "^1.22.1", 21 | "dotenv": "^16.0.3", 22 | "hardhat": "^2.14.0", 23 | "hardhat-contract-sizer": "^2.6.1", 24 | "hardhat-gas-reporter": "^1.0.9" 25 | }, 26 | "dependencies": { 27 | "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", 28 | "@nomicfoundation/hardhat-network-helpers": "^1.0.0", 29 | "@nomiclabs/hardhat-ethers": "^2.0.0", 30 | "@nomiclabs/hardhat-etherscan": "^3.0.0", 31 | "@typechain/ethers-v5": "^10.1.0", 32 | "@typechain/hardhat": "^6.1.2", 33 | "@types/chai": "^4.2.0", 34 | "@types/mocha": ">=9.1.0", 35 | "solidity-coverage": "^0.8.1", 36 | "ts-node": "^10.9.1", 37 | "typechain": "^8.1.0", 38 | "typescript": "^5.1.3", 39 | "web3": "^4.0.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /periphery/contracts/lens/TickLens.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | pragma abicoder v2; 4 | 5 | import '@agniswap/core/contracts/interfaces/IAgniPool.sol'; 6 | 7 | import '../interfaces/ITickLens.sol'; 8 | 9 | /// @title Tick Lens contract 10 | contract TickLens is ITickLens { 11 | /// @inheritdoc ITickLens 12 | function getPopulatedTicksInWord(address pool, int16 tickBitmapIndex) 13 | public 14 | view 15 | override 16 | returns (PopulatedTick[] memory populatedTicks) 17 | { 18 | // fetch bitmap 19 | uint256 bitmap = IAgniPool(pool).tickBitmap(tickBitmapIndex); 20 | 21 | // calculate the number of populated ticks 22 | uint256 numberOfPopulatedTicks; 23 | for (uint256 i = 0; i < 256; i++) { 24 | if (bitmap & (1 << i) > 0) numberOfPopulatedTicks++; 25 | } 26 | 27 | // fetch populated tick data 28 | int24 tickSpacing = IAgniPool(pool).tickSpacing(); 29 | populatedTicks = new PopulatedTick[](numberOfPopulatedTicks); 30 | for (uint256 i = 0; i < 256; i++) { 31 | if (bitmap & (1 << i) > 0) { 32 | int24 populatedTick = ((int24(tickBitmapIndex) << 8) + int24(i)) * tickSpacing; 33 | (uint128 liquidityGross, int128 liquidityNet, , , , , , ) = IAgniPool(pool).ticks(populatedTick); 34 | populatedTicks[--numberOfPopulatedTicks] = PopulatedTick({ 35 | tick: populatedTick, 36 | liquidityNet: liquidityNet, 37 | liquidityGross: liquidityGross 38 | }); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /core/scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | 4 | async function main() { 5 | const networkName = await network.name; 6 | console.log("Network name=", networkName); 7 | 8 | const AgniPoolDeployer = await ethers.getContractFactory( 9 | "AgniPoolDeployer" 10 | ); 11 | const agniPoolDeployer = await AgniPoolDeployer.deploy(); 12 | console.log("AgniPoolDeployer", agniPoolDeployer.address); 13 | 14 | const AgniFactory = await ethers.getContractFactory("AgniFactory"); 15 | const agniFactory = await AgniFactory.deploy(agniPoolDeployer.address); 16 | console.log("AgniFactory", agniFactory.address); 17 | 18 | let setFactoryAddressTx = await agniPoolDeployer.setFactoryAddress(agniFactory.address); 19 | console.log( 20 | "agniPoolDeployer setFactoryAddress tx:", 21 | setFactoryAddressTx.hash 22 | ); 23 | 24 | const OutputCodeHash = await ethers.getContractFactory("OutputCodeHash"); 25 | const outputCodeHash = await OutputCodeHash.deploy(); 26 | console.log("OutputCodeHash", outputCodeHash.address); 27 | 28 | const hash = await outputCodeHash.getInitCodeHash(); 29 | console.log("hash: ", hash); 30 | 31 | let contractAddresses = { 32 | AgniPoolDeployer: agniPoolDeployer.address, 33 | AgniFactory: agniFactory.address, 34 | InitCodeHashAddress: outputCodeHash.address, 35 | InitCodeHash: hash, 36 | }; 37 | await utils.writeContractAddresses(networkName,contractAddresses); 38 | } 39 | 40 | // We recommend this pattern to be able to use async/await everywhere 41 | // and properly handle errors. 42 | main().catch((error) => { 43 | console.error(error); 44 | process.exitCode = 1; 45 | }); 46 | -------------------------------------------------------------------------------- /periphery/test/shared/getPermitNFTSignature.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber, BigNumberish, constants, Signature, Wallet } from 'ethers' 2 | import { splitSignature } from 'ethers/lib/utils' 3 | import { NonfungiblePositionManager } from '../../typechain' 4 | 5 | export default async function getPermitNFTSignature( 6 | wallet: Wallet, 7 | positionManager: NonfungiblePositionManager, 8 | spender: string, 9 | tokenId: BigNumberish, 10 | deadline: BigNumberish = constants.MaxUint256, 11 | permitConfig?: { nonce?: BigNumberish; name?: string; chainId?: number; version?: string } 12 | ): Promise { 13 | const [nonce, name, version, chainId] = await Promise.all([ 14 | permitConfig?.nonce ?? positionManager.positions(tokenId).then((p) => p.nonce), 15 | permitConfig?.name ?? positionManager.name(), 16 | permitConfig?.version ?? '1', 17 | permitConfig?.chainId ?? wallet.getChainId(), 18 | ]) 19 | 20 | return splitSignature( 21 | await wallet._signTypedData( 22 | { 23 | name, 24 | version, 25 | chainId, 26 | verifyingContract: positionManager.address, 27 | }, 28 | { 29 | Permit: [ 30 | { 31 | name: 'spender', 32 | type: 'address', 33 | }, 34 | { 35 | name: 'tokenId', 36 | type: 'uint256', 37 | }, 38 | { 39 | name: 'nonce', 40 | type: 'uint256', 41 | }, 42 | { 43 | name: 'deadline', 44 | type: 'uint256', 45 | }, 46 | ], 47 | }, 48 | { 49 | owner: wallet.address, 50 | spender, 51 | tokenId, 52 | nonce, 53 | deadline, 54 | } 55 | ) 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /periphery/test/shared/permit.ts: -------------------------------------------------------------------------------- 1 | import { BigNumberish, constants, Signature, Wallet } from 'ethers' 2 | import { splitSignature } from 'ethers/lib/utils' 3 | import { TestERC20, TestERC20PermitAllowed } from '../../typechain' 4 | 5 | export async function getPermitSignature( 6 | wallet: Wallet, 7 | token: TestERC20 | TestERC20PermitAllowed, 8 | spender: string, 9 | value: BigNumberish = constants.MaxUint256, 10 | deadline = constants.MaxUint256, 11 | permitConfig?: { nonce?: BigNumberish; name?: string; chainId?: number; version?: string } 12 | ): Promise { 13 | const [nonce, name, version, chainId] = await Promise.all([ 14 | permitConfig?.nonce ?? token.nonces(wallet.address), 15 | permitConfig?.name ?? token.name(), 16 | permitConfig?.version ?? '1', 17 | permitConfig?.chainId ?? wallet.getChainId(), 18 | ]) 19 | 20 | return splitSignature( 21 | await wallet._signTypedData( 22 | { 23 | name, 24 | version, 25 | chainId, 26 | verifyingContract: token.address, 27 | }, 28 | { 29 | Permit: [ 30 | { 31 | name: 'owner', 32 | type: 'address', 33 | }, 34 | { 35 | name: 'spender', 36 | type: 'address', 37 | }, 38 | { 39 | name: 'value', 40 | type: 'uint256', 41 | }, 42 | { 43 | name: 'nonce', 44 | type: 'uint256', 45 | }, 46 | { 47 | name: 'deadline', 48 | type: 'uint256', 49 | }, 50 | ], 51 | }, 52 | { 53 | owner: wallet.address, 54 | spender, 55 | value, 56 | nonce, 57 | deadline, 58 | } 59 | ) 60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /periphery/scripts/swap.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | import { BigNumber } from "@ethersproject/bignumber"; 3 | const utils = require("../common/utils"); 4 | 5 | const agniAddress = "0x74a0E7118480bdfF5f812c7a879a41db09ac2c39"; 6 | let wmntAddress = ""; 7 | 8 | async function main() { 9 | const networkName = await network.name; 10 | console.log("Network name=", networkName); 11 | 12 | const [owner] = await ethers.getSigners(); 13 | let contractAddresses = utils.getContractAddresses(networkName,""); 14 | wmntAddress = contractAddresses.WMNT; 15 | 16 | const swapRouter = await ethers.getContractAt( 17 | "SwapRouter", 18 | contractAddresses.SwapRouter 19 | ); 20 | 21 | const MNT = await ethers.getContractAt("WMNT", wmntAddress); 22 | let mammApproveTx = await MNT.approve( 23 | contractAddresses.SwapRouter, 24 | BigNumber.from("10000000000000000000000000000") 25 | ); 26 | console.log("MNT approve tx:", mammApproveTx.hash); 27 | 28 | const AGNI = await ethers.getContractAt("SelfSufficientERC20", agniAddress); 29 | await AGNI.approve( 30 | contractAddresses.SwapRouter, 31 | BigNumber.from("10000000000000000000000000000") 32 | ); 33 | console.log("approve success"); 34 | 35 | await swapRouter.exactInputSingle({ 36 | tokenIn: wmntAddress, 37 | tokenOut: agniAddress, 38 | fee: 100, 39 | recipient: owner.address, 40 | deadline: 999999999, 41 | amountIn: BigNumber.from("11000000000000000000"), 42 | amountOutMinimum: 0, 43 | sqrtPriceLimitX96: 0, 44 | }); 45 | console.log("swap success"); 46 | } 47 | 48 | // We recommend this pattern to be able to use async/await everywhere 49 | // and properly handle errors. 50 | main().catch((error) => { 51 | console.error(error); 52 | process.exitCode = 1; 53 | }); 54 | -------------------------------------------------------------------------------- /farmbooster/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from "hardhat/config"; 2 | import "@nomicfoundation/hardhat-toolbox"; 3 | import "@nomiclabs/hardhat-etherscan"; 4 | import "@openzeppelin/hardhat-upgrades"; 5 | import "hardhat-gas-reporter"; 6 | import "hardhat-contract-sizer"; 7 | import dotenv from "dotenv"; 8 | dotenv.config(); 9 | 10 | const config: HardhatUserConfig = { 11 | solidity: { 12 | compilers: [ 13 | { 14 | version: "0.8.9", 15 | settings: { 16 | optimizer: { 17 | enabled: true, 18 | runs: 200, 19 | }, 20 | }, 21 | }, 22 | ], 23 | }, 24 | networks: { 25 | mantleTestnet: { 26 | url: process.env.MANTLE_TESTNET_URL || "", 27 | accounts: 28 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 29 | }, 30 | mantleMainnet: { 31 | url: process.env.MANTLE_URL || "", 32 | accounts: 33 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 34 | }, 35 | }, 36 | gasReporter: { 37 | enabled: process.env.REPORT_GAS !== undefined, 38 | currency: "USD", 39 | }, 40 | etherscan: { 41 | apiKey: process.env.MANTLESCAN_API_KEY, 42 | customChains: [ 43 | { 44 | network: "mantleTestnet", 45 | chainId: 5001, 46 | urls: { 47 | apiURL: "https://explorer.testnet.mantle.xyz/api", 48 | browserURL: "https://rpc.testnet.mantle.xyz", 49 | }, 50 | }, 51 | { 52 | network: "mantleMainnet", 53 | chainId: 5000, 54 | urls: { 55 | apiURL: "https://explorer.mantle.xyz/api", 56 | browserURL: "https://explorer.mantle.xyz/", 57 | }, 58 | }, 59 | ], 60 | }, 61 | }; 62 | 63 | export default config; 64 | -------------------------------------------------------------------------------- /v2-protocol/contracts/interfaces/IAgniPair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | import "./IAgniERC20.sol"; 4 | 5 | interface IAgniPair is IAgniERC20{ 6 | 7 | event Mint(address indexed sender, uint256 amount0, uint256 amount1); 8 | event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); 9 | event Swap( 10 | address indexed sender, 11 | uint256 amount0In, 12 | uint256 amount1In, 13 | uint256 amount0Out, 14 | uint256 amount1Out, 15 | address indexed to 16 | ); 17 | event Sync(uint112 reserve0, uint112 reserve1); 18 | 19 | function MINIMUM_LIQUIDITY() external pure returns (uint256); 20 | 21 | function factory() external view returns (address); 22 | 23 | function token0() external view returns (address); 24 | 25 | function token1() external view returns (address); 26 | 27 | function getReserves() 28 | external 29 | view 30 | returns ( 31 | uint112 reserve0, 32 | uint112 reserve1, 33 | uint32 blockTimestampLast 34 | ); 35 | 36 | function price0CumulativeLast() external view returns (uint256); 37 | 38 | function price1CumulativeLast() external view returns (uint256); 39 | 40 | function kLast() external view returns (uint256); 41 | 42 | function mint(address to) external returns (uint256 liquidity); 43 | 44 | function burn(address to) external returns (uint256 amount0, uint256 amount1); 45 | 46 | function swap( 47 | uint256 amount0Out, 48 | uint256 amount1Out, 49 | address to, 50 | bytes calldata data 51 | ) external; 52 | 53 | function skim(address to) external; 54 | 55 | function sync() external; 56 | 57 | function initialize(address, address) external; 58 | } 59 | -------------------------------------------------------------------------------- /core/contracts/libraries/LowGasSafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.0; 3 | 4 | /// @title Optimized overflow and underflow safe math operations 5 | /// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost 6 | library LowGasSafeMath { 7 | /// @notice Returns x + y, reverts if sum overflows uint256 8 | /// @param x The augend 9 | /// @param y The addend 10 | /// @return z The sum of x and y 11 | function add(uint256 x, uint256 y) internal pure returns (uint256 z) { 12 | require((z = x + y) >= x); 13 | } 14 | 15 | /// @notice Returns x - y, reverts if underflows 16 | /// @param x The minuend 17 | /// @param y The subtrahend 18 | /// @return z The difference of x and y 19 | function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { 20 | require((z = x - y) <= x); 21 | } 22 | 23 | /// @notice Returns x * y, reverts if overflows 24 | /// @param x The multiplicand 25 | /// @param y The multiplier 26 | /// @return z The product of x and y 27 | function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { 28 | require(x == 0 || (z = x * y) / x == y); 29 | } 30 | 31 | /// @notice Returns x + y, reverts if overflows or underflows 32 | /// @param x The augend 33 | /// @param y The addend 34 | /// @return z The sum of x and y 35 | function add(int256 x, int256 y) internal pure returns (int256 z) { 36 | require((z = x + y) >= x == (y >= 0)); 37 | } 38 | 39 | /// @notice Returns x - y, reverts if overflows or underflows 40 | /// @param x The minuend 41 | /// @param y The subtrahend 42 | /// @return z The difference of x and y 43 | function sub(int256 x, int256 y) internal pure returns (int256 z) { 44 | require((z = x - y) <= x == (y >= 0)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@agniswap/core", 3 | "version": "1.0.1", 4 | "description": "Core smart contracts of Agni Protocol", 5 | "license": "GPL-2.0-or-later", 6 | "publishConfig": { 7 | "access": "public" 8 | }, 9 | "keywords": [ 10 | "agniswap", 11 | "core" 12 | ], 13 | "files": [ 14 | "contracts/interfaces", 15 | "contracts/libraries", 16 | "artifacts/contracts/AgniFactory.sol/AgniFactory.json", 17 | "artifacts/contracts/AgniPool.sol/AgniPool.json", 18 | "artifacts/contracts/interfaces/**/*.json", 19 | "!artifacts/contracts/interfaces/**/*.dbg.json" 20 | ], 21 | "engines": { 22 | "node": ">=10" 23 | }, 24 | "scripts": { 25 | "deploy": "hardhat run scripts/deploy.ts --network", 26 | "pool_address": "hardhat run scripts/pool_address.ts --network", 27 | "collect_fee": "hardhat run scripts/collect_fee.ts --network", 28 | "verify": "hardhat run scripts/verify.ts --network" 29 | }, 30 | "devDependencies": { 31 | "@nomicfoundation/hardhat-chai-matchers": "2.0.2", 32 | "@nomicfoundation/hardhat-ethers": "3.0.4", 33 | "@nomicfoundation/hardhat-network-helpers": "1.0.8", 34 | "@nomicfoundation/hardhat-toolbox": "3.0.0", 35 | "@nomicfoundation/hardhat-verify": "^1.1.1", 36 | "@typechain/ethers-v6": "0.5.0", 37 | "@typechain/hardhat": "9.0.0", 38 | "@types/chai": "4.3.5", 39 | "@types/mocha": "10.0.1", 40 | "@types/node": "20.5.6", 41 | "chai": "4.3.8", 42 | "dotenv": "^16.3.1", 43 | "ethers": "6.1.0", 44 | "hardhat": "2.17.1", 45 | "hardhat-contract-sizer": "^2.10.0", 46 | "hardhat-deploy": "0.11.37", 47 | "hardhat-deploy-ethers": "0.4.1", 48 | "hardhat-gas-reporter": "1.0.9", 49 | "solidity-coverage": "0.8.4", 50 | "ts-node": "10.9.1", 51 | "typechain": "8.3.1", 52 | "typescript": "5.2.2" 53 | }, 54 | "dependencies": { 55 | "web3": "^4.0.3" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/contracts/interfaces/pool/IAgniPoolImmutables.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Pool state that never changes 5 | /// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values 6 | interface IAgniPoolImmutables { 7 | /// @notice The contract that deployed the pool, which must adhere to the IAgniFactory interface 8 | /// @return The contract address 9 | function factory() external view returns (address); 10 | 11 | /// @notice The first of the two tokens of the pool, sorted by address 12 | /// @return The token contract address 13 | function token0() external view returns (address); 14 | 15 | /// @notice The second of the two tokens of the pool, sorted by address 16 | /// @return The token contract address 17 | function token1() external view returns (address); 18 | 19 | /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6 20 | /// @return The fee 21 | function fee() external view returns (uint24); 22 | 23 | /// @notice The pool tick spacing 24 | /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive 25 | /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ... 26 | /// This value is an int24 to avoid casting even though it is always positive. 27 | /// @return The tick spacing 28 | function tickSpacing() external view returns (int24); 29 | 30 | /// @notice The maximum amount of position liquidity that can use any tick in the range 31 | /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and 32 | /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool 33 | /// @return The max amount of liquidity per tick 34 | function maxLiquidityPerTick() external view returns (uint128); 35 | } 36 | -------------------------------------------------------------------------------- /core/contracts/test/TickBitmapEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/TickBitmap.sol'; 5 | 6 | contract TickBitmapEchidnaTest { 7 | using TickBitmap for mapping(int16 => uint256); 8 | 9 | mapping(int16 => uint256) private bitmap; 10 | 11 | // returns whether the given tick is initialized 12 | function isInitialized(int24 tick) private view returns (bool) { 13 | (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(tick, 1, true); 14 | return next == tick ? initialized : false; 15 | } 16 | 17 | function flipTick(int24 tick) external { 18 | bool before = isInitialized(tick); 19 | bitmap.flipTick(tick, 1); 20 | assert(isInitialized(tick) == !before); 21 | } 22 | 23 | function checkNextInitializedTickWithinOneWordInvariants(int24 tick, bool lte) external view { 24 | (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(tick, 1, lte); 25 | if (lte) { 26 | // type(int24).min + 256 27 | require(tick >= -8388352); 28 | assert(next <= tick); 29 | assert(tick - next < 256); 30 | // all the ticks between the input tick and the next tick should be uninitialized 31 | for (int24 i = tick; i > next; i--) { 32 | assert(!isInitialized(i)); 33 | } 34 | assert(isInitialized(next) == initialized); 35 | } else { 36 | // type(int24).max - 256 37 | require(tick < 8388351); 38 | assert(next > tick); 39 | assert(next - tick <= 256); 40 | // all the ticks between the input tick and the next tick should be uninitialized 41 | for (int24 i = tick + 1; i < next; i++) { 42 | assert(!isInitialized(i)); 43 | } 44 | assert(isInitialized(next) == initialized); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /periphery/contracts/test/MockObservable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | contract MockObservable { 5 | Observation private observation0; 6 | Observation private observation1; 7 | 8 | struct Observation { 9 | uint32 secondsAgo; 10 | int56 tickCumulatives; 11 | uint160 secondsPerLiquidityCumulativeX128s; 12 | } 13 | 14 | constructor( 15 | uint32[] memory secondsAgos, 16 | int56[] memory tickCumulatives, 17 | uint160[] memory secondsPerLiquidityCumulativeX128s 18 | ) { 19 | require( 20 | secondsAgos.length == 2 && tickCumulatives.length == 2 && secondsPerLiquidityCumulativeX128s.length == 2, 21 | 'Invalid test case size' 22 | ); 23 | 24 | observation0 = Observation(secondsAgos[0], tickCumulatives[0], secondsPerLiquidityCumulativeX128s[0]); 25 | observation1 = Observation(secondsAgos[1], tickCumulatives[1], secondsPerLiquidityCumulativeX128s[1]); 26 | } 27 | 28 | function observe(uint32[] calldata secondsAgos) 29 | external 30 | view 31 | returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s) 32 | { 33 | require( 34 | secondsAgos[0] == observation0.secondsAgo && secondsAgos[1] == observation1.secondsAgo, 35 | 'Invalid test case' 36 | ); 37 | 38 | int56[] memory _tickCumulatives = new int56[](2); 39 | _tickCumulatives[0] = observation0.tickCumulatives; 40 | _tickCumulatives[1] = observation1.tickCumulatives; 41 | 42 | uint160[] memory _secondsPerLiquidityCumulativeX128s = new uint160[](2); 43 | _secondsPerLiquidityCumulativeX128s[0] = observation0.secondsPerLiquidityCumulativeX128s; 44 | _secondsPerLiquidityCumulativeX128s[1] = observation1.secondsPerLiquidityCumulativeX128s; 45 | 46 | return (_tickCumulatives, _secondsPerLiquidityCumulativeX128s); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /periphery/contracts/test/PositionValueTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/PositionValue.sol'; 5 | import '../interfaces/INonfungiblePositionManager.sol'; 6 | 7 | contract PositionValueTest { 8 | function total( 9 | INonfungiblePositionManager nft, 10 | uint256 tokenId, 11 | uint160 sqrtRatioX96 12 | ) external view returns (uint256 amount0, uint256 amount1) { 13 | return PositionValue.total(nft, tokenId, sqrtRatioX96); 14 | } 15 | 16 | function principal( 17 | INonfungiblePositionManager nft, 18 | uint256 tokenId, 19 | uint160 sqrtRatioX96 20 | ) external view returns (uint256 amount0, uint256 amount1) { 21 | return PositionValue.principal(nft, tokenId, sqrtRatioX96); 22 | } 23 | 24 | function fees(INonfungiblePositionManager nft, uint256 tokenId) 25 | external 26 | view 27 | returns (uint256 amount0, uint256 amount1) 28 | { 29 | return PositionValue.fees(nft, tokenId); 30 | } 31 | 32 | function totalGas( 33 | INonfungiblePositionManager nft, 34 | uint256 tokenId, 35 | uint160 sqrtRatioX96 36 | ) external view returns (uint256) { 37 | uint256 gasBefore = gasleft(); 38 | PositionValue.total(nft, tokenId, sqrtRatioX96); 39 | return gasBefore - gasleft(); 40 | } 41 | 42 | function principalGas( 43 | INonfungiblePositionManager nft, 44 | uint256 tokenId, 45 | uint160 sqrtRatioX96 46 | ) external view returns (uint256) { 47 | uint256 gasBefore = gasleft(); 48 | PositionValue.principal(nft, tokenId, sqrtRatioX96); 49 | return gasBefore - gasleft(); 50 | } 51 | 52 | function feesGas(INonfungiblePositionManager nft, uint256 tokenId) external view returns (uint256) { 53 | uint256 gasBefore = gasleft(); 54 | PositionValue.fees(nft, tokenId); 55 | return gasBefore - gasleft(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/contracts/test/FullMathEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/FullMath.sol'; 5 | 6 | contract FullMathEchidnaTest { 7 | function checkMulDivRounding( 8 | uint256 x, 9 | uint256 y, 10 | uint256 d 11 | ) external pure { 12 | require(d > 0); 13 | 14 | uint256 ceiled = FullMath.mulDivRoundingUp(x, y, d); 15 | uint256 floored = FullMath.mulDiv(x, y, d); 16 | 17 | if (mulmod(x, y, d) > 0) { 18 | assert(ceiled - floored == 1); 19 | } else { 20 | assert(ceiled == floored); 21 | } 22 | } 23 | 24 | function checkMulDiv( 25 | uint256 x, 26 | uint256 y, 27 | uint256 d 28 | ) external pure { 29 | require(d > 0); 30 | uint256 z = FullMath.mulDiv(x, y, d); 31 | if (x == 0 || y == 0) { 32 | assert(z == 0); 33 | return; 34 | } 35 | 36 | // recompute x and y via mulDiv of the result of floor(x*y/d), should always be less than original inputs by < d 37 | uint256 x2 = FullMath.mulDiv(z, d, y); 38 | uint256 y2 = FullMath.mulDiv(z, d, x); 39 | assert(x2 <= x); 40 | assert(y2 <= y); 41 | 42 | assert(x - x2 < d); 43 | assert(y - y2 < d); 44 | } 45 | 46 | function checkMulDivRoundingUp( 47 | uint256 x, 48 | uint256 y, 49 | uint256 d 50 | ) external pure { 51 | require(d > 0); 52 | uint256 z = FullMath.mulDivRoundingUp(x, y, d); 53 | if (x == 0 || y == 0) { 54 | assert(z == 0); 55 | return; 56 | } 57 | 58 | // recompute x and y via mulDiv of the result of floor(x*y/d), should always be less than original inputs by < d 59 | uint256 x2 = FullMath.mulDiv(z, d, y); 60 | uint256 y2 = FullMath.mulDiv(z, d, x); 61 | assert(x2 >= x); 62 | assert(y2 >= y); 63 | 64 | assert(x2 - x < d); 65 | assert(y2 - y < d); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /launchpad/contracts/interfaces/IInsurancePool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.7.6; 3 | pragma abicoder v2; 4 | 5 | interface IInsurancePool { 6 | struct IdoPoolInfo { 7 | address paymentToken; 8 | uint256 presalePrice; 9 | uint256 publicSalePrice; 10 | uint256 avgPrice; 11 | uint256 presaleTotalQuota; 12 | uint256 publicSaleTotalQuota; 13 | uint256 needToPay; 14 | uint256 sellingTokenExp; 15 | } 16 | 17 | struct InsuranceDetail { 18 | address idoPool; 19 | address token; 20 | address user; 21 | uint256 buyQuota; 22 | uint256 price; 23 | bool lossClaimed; 24 | } 25 | 26 | event IdoPoolRegistered(address indexed idoPool); 27 | event Insured( 28 | address indexed idoPool, 29 | address indexed token, 30 | address indexed user, 31 | uint256 buyQuota, 32 | uint256 price, 33 | uint256 insuranceId 34 | ); 35 | event LossClaimed( 36 | address indexed operator, 37 | address indexed user, 38 | address indexed token, 39 | uint256 insuranceId, 40 | uint256 payAmount 41 | ); 42 | 43 | function factory() external view returns (address); 44 | function isRegisteredPool(address pool) external view returns (bool); 45 | function getInsuranceDetail(uint256 insuranceId) external view returns (InsuranceDetail memory); 46 | function getInsuranceIdsByUser(address user) external view returns (uint256[] memory); 47 | function getIdoPoolInfo(address pool) external view returns (IdoPoolInfo memory); 48 | function totalNeedToPayByToken(address token) external view returns (uint256); 49 | 50 | function registerIdoPool(address idoPool) external; 51 | function insure(address user, uint256 buyQuota, uint256 price, bool isPresale) external returns (uint256 insuranceId); 52 | function setAvgPrice(address pool, uint256 price, bool scam) external; 53 | function claimLoss(uint256 insuranceId) external; 54 | } -------------------------------------------------------------------------------- /periphery/test/shared/path.ts: -------------------------------------------------------------------------------- 1 | import { utils } from 'ethers' 2 | import { FeeAmount } from './constants' 3 | 4 | const ADDR_SIZE = 20 5 | const FEE_SIZE = 3 6 | const OFFSET = ADDR_SIZE + FEE_SIZE 7 | const DATA_SIZE = OFFSET + ADDR_SIZE 8 | 9 | export function encodePath(path: string[], fees: FeeAmount[]): string { 10 | if (path.length != fees.length + 1) { 11 | throw new Error('path/fee lengths do not match') 12 | } 13 | 14 | let encoded = '0x' 15 | for (let i = 0; i < fees.length; i++) { 16 | // 20 byte encoding of the address 17 | encoded += path[i].slice(2) 18 | // 3 byte encoding of the fee 19 | encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0') 20 | } 21 | // encode the final token 22 | encoded += path[path.length - 1].slice(2) 23 | 24 | return encoded.toLowerCase() 25 | } 26 | 27 | function decodeOne(tokenFeeToken: Buffer): [[string, string], number] { 28 | // reads the first 20 bytes for the token address 29 | const tokenABuf = tokenFeeToken.slice(0, ADDR_SIZE) 30 | const tokenA = utils.getAddress('0x' + tokenABuf.toString('hex')) 31 | 32 | // reads the next 2 bytes for the fee 33 | const feeBuf = tokenFeeToken.slice(ADDR_SIZE, OFFSET) 34 | const fee = feeBuf.readUIntBE(0, FEE_SIZE) 35 | 36 | // reads the next 20 bytes for the token address 37 | const tokenBBuf = tokenFeeToken.slice(OFFSET, DATA_SIZE) 38 | const tokenB = utils.getAddress('0x' + tokenBBuf.toString('hex')) 39 | 40 | return [[tokenA, tokenB], fee] 41 | } 42 | 43 | export function decodePath(path: string): [string[], number[]] { 44 | let data = Buffer.from(path.slice(2), 'hex') 45 | 46 | let tokens: string[] = [] 47 | let fees: number[] = [] 48 | let i = 0 49 | let finalToken: string = '' 50 | while (data.length >= DATA_SIZE) { 51 | const [[tokenA, tokenB], fee] = decodeOne(data) 52 | finalToken = tokenB 53 | tokens = [...tokens, tokenA] 54 | fees = [...fees, fee] 55 | data = data.slice((i + 1) * OFFSET) 56 | i += 1 57 | } 58 | tokens = [...tokens, finalToken] 59 | 60 | return [tokens, fees] 61 | } 62 | -------------------------------------------------------------------------------- /core/contracts/test/SwapMathEchidnaTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity =0.7.6; 3 | 4 | import '../libraries/SwapMath.sol'; 5 | 6 | contract SwapMathEchidnaTest { 7 | function checkComputeSwapStepInvariants( 8 | uint160 sqrtPriceRaw, 9 | uint160 sqrtPriceTargetRaw, 10 | uint128 liquidity, 11 | int256 amountRemaining, 12 | uint24 feePips 13 | ) external pure { 14 | require(sqrtPriceRaw > 0); 15 | require(sqrtPriceTargetRaw > 0); 16 | require(feePips > 0); 17 | require(feePips < 1e6); 18 | 19 | (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = SwapMath.computeSwapStep( 20 | sqrtPriceRaw, 21 | sqrtPriceTargetRaw, 22 | liquidity, 23 | amountRemaining, 24 | feePips 25 | ); 26 | 27 | assert(amountIn <= type(uint256).max - feeAmount); 28 | 29 | if (amountRemaining < 0) { 30 | assert(amountOut <= uint256(-amountRemaining)); 31 | } else { 32 | assert(amountIn + feeAmount <= uint256(amountRemaining)); 33 | } 34 | 35 | if (sqrtPriceRaw == sqrtPriceTargetRaw) { 36 | assert(amountIn == 0); 37 | assert(amountOut == 0); 38 | assert(feeAmount == 0); 39 | assert(sqrtQ == sqrtPriceTargetRaw); 40 | } 41 | 42 | // didn't reach price target, entire amount must be consumed 43 | if (sqrtQ != sqrtPriceTargetRaw) { 44 | if (amountRemaining < 0) assert(amountOut == uint256(-amountRemaining)); 45 | else assert(amountIn + feeAmount == uint256(amountRemaining)); 46 | } 47 | 48 | // next price is between price and price target 49 | if (sqrtPriceTargetRaw <= sqrtPriceRaw) { 50 | assert(sqrtQ <= sqrtPriceRaw); 51 | assert(sqrtQ >= sqrtPriceTargetRaw); 52 | } else { 53 | assert(sqrtQ >= sqrtPriceRaw); 54 | assert(sqrtQ <= sqrtPriceTargetRaw); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /periphery/contracts/libraries/PoolAddress.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Provides functions for deriving a pool address from the factory, tokens, and the fee 5 | library PoolAddress { 6 | bytes32 internal constant POOL_INIT_CODE_HASH = 0xaf9bd540c3449b723624376f906d8d3a0e6441ff18b847f05f4f85789ab64d9a; 7 | 8 | /// @notice The identifying key of the pool 9 | struct PoolKey { 10 | address token0; 11 | address token1; 12 | uint24 fee; 13 | } 14 | 15 | /// @notice Returns PoolKey: the ordered tokens with the matched fee levels 16 | /// @param tokenA The first token of a pool, unsorted 17 | /// @param tokenB The second token of a pool, unsorted 18 | /// @param fee The fee level of the pool 19 | /// @return Poolkey The pool details with ordered token0 and token1 assignments 20 | function getPoolKey( 21 | address tokenA, 22 | address tokenB, 23 | uint24 fee 24 | ) internal pure returns (PoolKey memory) { 25 | if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); 26 | return PoolKey({token0: tokenA, token1: tokenB, fee: fee}); 27 | } 28 | 29 | /// @notice Deterministically computes the pool address given the deployer and PoolKey 30 | /// @param deployer The Agni deployer contract address 31 | /// @param key The PoolKey 32 | /// @return pool The contract address of the V3 pool 33 | function computeAddress(address deployer, PoolKey memory key) internal pure returns (address pool) { 34 | require(key.token0 < key.token1); 35 | pool = address( 36 | uint256( 37 | keccak256( 38 | abi.encodePacked( 39 | hex'ff', 40 | deployer, 41 | keccak256(abi.encode(key.token0, key.token1, key.fee)), 42 | POOL_INIT_CODE_HASH 43 | ) 44 | ) 45 | ) 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /periphery/scripts/init_pool.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | const {encodePriceSqrt} = require("../test/shared/encodePriceSqrt"); 4 | const {formatSqrtRatioX96 } = require("../test/shared/formatSqrtRatioX96"); 5 | 6 | let wmntAddress = ""; 7 | const usdcAddress = "0x74a0E7118480bdfF5f812c7a879a41db09ac2c39"; // testnet 8 | // const usdcAddress = "0x201eba5cc46d216ce6dc03f6a759e8e766e956ae"; // mainnet 9 | 10 | async function main() { 11 | const networkName = await network.name; 12 | console.log("Network name=", networkName); 13 | 14 | let coreContractAddresses = utils.getContractAddresses( 15 | networkName, 16 | `../core/deployments/${networkName}.json` 17 | ); 18 | console.log("core contract addresses:", coreContractAddresses); 19 | 20 | let contractAddresses = utils.getContractAddresses(networkName, ""); 21 | console.log("contractAddresses:", contractAddresses); 22 | wmntAddress = contractAddresses.WMNT; 23 | 24 | // Agni/WMNT = 2 25 | let price = encodePriceSqrt(2, 1); 26 | console.log("sqrtPrice:", price); 27 | 28 | let priceStr = formatSqrtRatioX96(price); 29 | console.log("priceStr:", priceStr); 30 | 31 | const positionManager = await ethers.getContractAt( 32 | "NonfungiblePositionManager", 33 | contractAddresses.NonfungiblePositionManager 34 | ); 35 | 36 | let token0 = wmntAddress < usdcAddress ? wmntAddress : usdcAddress; 37 | let token1 = usdcAddress > wmntAddress ? usdcAddress : wmntAddress; 38 | console.log("token0:", token0); 39 | console.log("token1:", token1); 40 | 41 | let initPoolTx = await positionManager.createAndInitializePoolIfNecessary( 42 | wmntAddress < usdcAddress ? wmntAddress : usdcAddress, 43 | usdcAddress > wmntAddress ? usdcAddress : wmntAddress, 44 | 500, 45 | price 46 | ); 47 | console.log("initPoolTx pool success:", initPoolTx.hash); 48 | } 49 | 50 | // We recommend this pattern to be able to use async/await everywhere 51 | // and properly handle errors. 52 | main().catch((error) => { 53 | console.error(error); 54 | process.exitCode = 1; 55 | }); 56 | -------------------------------------------------------------------------------- /core/contracts/AgniPoolDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity =0.7.6; 3 | 4 | import './interfaces/IAgniPoolDeployer.sol'; 5 | import './AgniPool.sol'; 6 | 7 | contract AgniPoolDeployer is IAgniPoolDeployer { 8 | struct Parameters { 9 | address factory; 10 | address token0; 11 | address token1; 12 | uint24 fee; 13 | int24 tickSpacing; 14 | } 15 | 16 | /// @inheritdoc IAgniPoolDeployer 17 | Parameters public override parameters; 18 | 19 | address public factoryAddress; 20 | 21 | /// @notice Emitted when factory address is set 22 | event SetFactoryAddress(address indexed factory); 23 | 24 | modifier onlyFactory() { 25 | require(msg.sender == factoryAddress, "only factory can call deploy"); 26 | _; 27 | } 28 | 29 | function setFactoryAddress(address _factoryAddress) external { 30 | require(factoryAddress == address(0), "already initialized"); 31 | 32 | factoryAddress = _factoryAddress; 33 | 34 | emit SetFactoryAddress(_factoryAddress); 35 | } 36 | 37 | /// @dev Deploys a pool with the given parameters by transiently setting the parameters storage slot and then 38 | /// clearing it after deploying the pool. 39 | /// @param factory The contract address of the Agni factory 40 | /// @param token0 The first token of the pool by address sort order 41 | /// @param token1 The second token of the pool by address sort order 42 | /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip 43 | /// @param tickSpacing The spacing between usable ticks 44 | function deploy( 45 | address factory, 46 | address token0, 47 | address token1, 48 | uint24 fee, 49 | int24 tickSpacing 50 | ) external override onlyFactory returns (address pool) { 51 | parameters = Parameters({factory: factory, token0: token0, token1: token1, fee: fee, tickSpacing: tickSpacing}); 52 | pool = address(new AgniPool{salt: keccak256(abi.encode(token0, token1, fee))}()); 53 | delete parameters; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /v2-protocol/contracts/AgniFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity =0.7.6; 3 | 4 | import './interfaces/IAgniFactory.sol'; 5 | import './AgniPair.sol'; 6 | 7 | contract AgniFactory is IAgniFactory { 8 | bytes32 public constant override INIT_CODE_PAIR_HASH = keccak256(abi.encodePacked(type(AgniPair).creationCode)); 9 | 10 | address public override feeTo; 11 | address public override feeToSetter; 12 | 13 | mapping(address => mapping(address => address)) public override getPair; 14 | address[] public override allPairs; 15 | 16 | constructor(address _feeToSetter) public { 17 | feeToSetter = _feeToSetter; 18 | } 19 | 20 | function allPairsLength() external override view returns (uint) { 21 | return allPairs.length; 22 | } 23 | 24 | function createPair(address tokenA, address tokenB) external override returns (address pair) { 25 | require(tokenA != tokenB, 'Agni: IDENTICAL_ADDRESSES'); 26 | (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 27 | require(token0 != address(0), 'Agni: ZERO_ADDRESS'); 28 | require(getPair[token0][token1] == address(0), 'Agni: PAIR_EXISTS'); // single check is sufficient 29 | bytes memory bytecode = type(AgniPair).creationCode; 30 | bytes32 salt = keccak256(abi.encodePacked(token0, token1)); 31 | assembly { 32 | pair := create2(0, add(bytecode, 32), mload(bytecode), salt) 33 | } 34 | IAgniPair(pair).initialize(token0, token1); 35 | getPair[token0][token1] = pair; 36 | getPair[token1][token0] = pair; // populate mapping in the reverse direction 37 | allPairs.push(pair); 38 | emit PairCreated(token0, token1, pair, allPairs.length); 39 | } 40 | 41 | function setFeeTo(address _feeTo) external override { 42 | require(msg.sender == feeToSetter, 'Agni: FORBIDDEN'); 43 | feeTo = _feeTo; 44 | } 45 | 46 | function setFeeToSetter(address _feeToSetter) external override{ 47 | require(msg.sender == feeToSetter, 'Agni: FORBIDDEN'); 48 | feeToSetter = _feeToSetter; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lm-pool/scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | import { abi } from "@agniswap/core/artifacts/contracts/AgniFactory.sol/AgniFactory.json"; 3 | const utils = require("../../common/utils"); 4 | 5 | let WMNT=""; 6 | let AGNI=""; 7 | 8 | async function main() { 9 | const networkName = await network.name; 10 | console.log("Network name=", networkName); 11 | 12 | let coreContractAddresses = utils.getContractAddresses( 13 | networkName,`../core/deployments/${networkName}.json` 14 | ); 15 | console.log("core contract addresses:", coreContractAddresses); 16 | 17 | let masterChefContractAddresses = utils.getContractAddresses( 18 | networkName,`../masterChef/deployments/${networkName}.json` 19 | ); 20 | console.log("masterChef contract addresses:", masterChefContractAddresses); 21 | 22 | if (networkName == "mantleMainnet") { 23 | WMNT = "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"; 24 | AGNI = ""; 25 | } else { 26 | WMNT = "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF"; 27 | AGNI = "0xd3b2241BfF9654195F814a15CbAc458C72Fa5084"; 28 | } 29 | console.log("WMNT addresses:", WMNT); 30 | 31 | 32 | const AgniLmPoolDeployer = await ethers.getContractFactory( 33 | "AgniLmPoolDeployer" 34 | ); 35 | const agniLmPoolDeployer = await AgniLmPoolDeployer.deploy( 36 | masterChefContractAddresses.MasterChef 37 | ); 38 | console.log("AgniLmPoolDeployer", agniLmPoolDeployer.address); 39 | 40 | let contractAddresses = { 41 | AgniLmPoolDeployer: agniLmPoolDeployer.address, 42 | }; 43 | await utils.writeContractAddresses(networkName,contractAddresses); 44 | 45 | const [owner] = await ethers.getSigners(); 46 | const agniFactory = new ethers.Contract( 47 | coreContractAddresses.AgniFactory, 48 | abi, 49 | owner 50 | ); 51 | let tx = await agniFactory.setLmPoolDeployer(agniLmPoolDeployer.address); 52 | console.log("SetLmPoolDeployer success, tx: ", tx.hash); 53 | } 54 | 55 | // We recommend this pattern to be able to use async/await everywhere 56 | // and properly handle errors. 57 | main().catch((error) => { 58 | console.error(error); 59 | process.exitCode = 1; 60 | }); 61 | -------------------------------------------------------------------------------- /periphery/contracts/base/PeripheryPaymentsWithFee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | 4 | import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; 5 | import '@agniswap/core/contracts/libraries/LowGasSafeMath.sol'; 6 | 7 | import './PeripheryPayments.sol'; 8 | import '../interfaces/IPeripheryPaymentsWithFee.sol'; 9 | 10 | import '../interfaces/external/IWMNT.sol'; 11 | import '../libraries/TransferHelper.sol'; 12 | 13 | abstract contract PeripheryPaymentsWithFee is PeripheryPayments, IPeripheryPaymentsWithFee { 14 | using LowGasSafeMath for uint256; 15 | 16 | /// @inheritdoc IPeripheryPaymentsWithFee 17 | function unwrapWMNTWithFee( 18 | uint256 amountMinimum, 19 | address recipient, 20 | uint256 feeBips, 21 | address feeRecipient 22 | ) public payable override { 23 | require(feeBips > 0 && feeBips <= 100); 24 | 25 | uint256 balanceWMNT = IWMNT(WMNT).balanceOf(address(this)); 26 | require(balanceWMNT >= amountMinimum, 'Insufficient WMNT'); 27 | 28 | if (balanceWMNT > 0) { 29 | IWMNT(WMNT).withdraw(balanceWMNT); 30 | uint256 feeAmount = balanceWMNT.mul(feeBips) / 10_000; 31 | if (feeAmount > 0) TransferHelper.safeTransferMNT(feeRecipient, feeAmount); 32 | TransferHelper.safeTransferMNT(recipient, balanceWMNT - feeAmount); 33 | } 34 | } 35 | 36 | /// @inheritdoc IPeripheryPaymentsWithFee 37 | function sweepTokenWithFee( 38 | address token, 39 | uint256 amountMinimum, 40 | address recipient, 41 | uint256 feeBips, 42 | address feeRecipient 43 | ) public payable override { 44 | require(feeBips > 0 && feeBips <= 100); 45 | 46 | uint256 balanceToken = IERC20(token).balanceOf(address(this)); 47 | require(balanceToken >= amountMinimum, 'Insufficient token'); 48 | 49 | if (balanceToken > 0) { 50 | uint256 feeAmount = balanceToken.mul(feeBips) / 10_000; 51 | if (feeAmount > 0) TransferHelper.safeTransfer(token, feeRecipient, feeAmount); 52 | TransferHelper.safeTransfer(token, recipient, balanceToken - feeAmount); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /periphery/contracts/test/WMNT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GNU GENERAL PUBLIC LICENSE V3 2 | pragma solidity =0.7.6; 3 | 4 | contract WMNT { 5 | string public name = "Wrapped MNT"; 6 | string public symbol = "WMNT"; 7 | uint8 public decimals = 18; 8 | 9 | event Approval(address indexed src, address indexed guy, uint256 wad); 10 | event Transfer(address indexed src, address indexed dst, uint256 wad); 11 | event Deposit(address indexed dst, uint256 wad); 12 | event Withdrawal(address indexed src, uint256 wad); 13 | 14 | mapping(address => uint256) public balanceOf; 15 | mapping(address => mapping(address => uint256)) public allowance; 16 | 17 | receive() external payable { 18 | deposit(); 19 | } 20 | 21 | function deposit() public payable { 22 | balanceOf[msg.sender] += msg.value; 23 | emit Deposit(msg.sender, msg.value); 24 | } 25 | 26 | function withdraw(uint256 wad) public { 27 | require(balanceOf[msg.sender] >= wad); 28 | balanceOf[msg.sender] -= wad; 29 | payable(msg.sender).transfer(wad); 30 | emit Withdrawal(msg.sender, wad); 31 | } 32 | 33 | function totalSupply() public view returns (uint256) { 34 | return address(this).balance; 35 | } 36 | 37 | function approve(address guy, uint256 wad) public returns (bool) { 38 | allowance[msg.sender][guy] = wad; 39 | emit Approval(msg.sender, guy, wad); 40 | return true; 41 | } 42 | 43 | function transfer(address dst, uint256 wad) public returns (bool) { 44 | return transferFrom(msg.sender, dst, wad); 45 | } 46 | 47 | function transferFrom( 48 | address src, 49 | address dst, 50 | uint256 wad 51 | ) public returns (bool) { 52 | require(balanceOf[src] >= wad); 53 | 54 | if ( 55 | src != msg.sender && allowance[src][msg.sender] != type(uint256).max 56 | ) { 57 | require(allowance[src][msg.sender] >= wad); 58 | allowance[src][msg.sender] -= wad; 59 | } 60 | 61 | balanceOf[src] -= wad; 62 | balanceOf[dst] += wad; 63 | 64 | emit Transfer(src, dst, wad); 65 | 66 | return true; 67 | } 68 | } -------------------------------------------------------------------------------- /masterchef/scripts/verify.ts: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const {network} = require("hardhat"); 3 | const utils = require("../../common/utils"); 4 | 5 | async function main() { 6 | const networkName = await network.name; 7 | console.log("Network name=", networkName); 8 | 9 | let peripheryContractAddresses = utils.getContractAddresses( 10 | networkName,`../periphery/deployments/${networkName}.json` 11 | ); 12 | console.log("periphery contract addresses:", peripheryContractAddresses); 13 | 14 | let contractAddresses = utils.getContractAddresses(networkName, ""); 15 | console.log("WMNT addresses:", contractAddresses.WMNT); 16 | console.log("AGNI addresses:", contractAddresses.MasterChefToken); 17 | 18 | await hre.run("verify:verify", { 19 | address: contractAddresses.MasterChef, 20 | contract: "contracts/MasterChef.sol:MasterChef", 21 | constructorArguments: [ 22 | contractAddresses.MasterChefToken, 23 | peripheryContractAddresses.NonfungiblePositionManager, 24 | contractAddresses.WMNT, 25 | ], 26 | }); 27 | 28 | await hre.run("verify:verify", { 29 | address: contractAddresses.ExtraIncentivePool, 30 | contract: "contracts/ExtraIncentivePool.sol:ExtraIncentivePool", 31 | constructorArguments: [ 32 | contractAddresses.IncentiveToken, 33 | contractAddresses.MasterChef, 34 | ], 35 | }); 36 | 37 | await hre.run("verify:verify", { 38 | address: contractAddresses.MasterChefV3Receiver, 39 | contract: 40 | "contracts/receiver/MasterChefV3Receiver.sol:MasterChefV3Receiver", 41 | constructorArguments: [contractAddresses.MasterChef, contractAddresses.MasterChefToken], 42 | }); 43 | 44 | await hre.run("verify:verify", { 45 | address: contractAddresses.IncentivePoolReceiver, 46 | contract: 47 | "contracts/receiver/IncentivePoolReceiver.sol:IncentivePoolReceiver", 48 | constructorArguments: [ 49 | contractAddresses.ExtraIncentivePool, 50 | contractAddresses.IncentiveToken, 51 | ], 52 | }); 53 | } 54 | 55 | // We recommend this pattern to be able to use async/await everywhere 56 | // and properly handle errors. 57 | main().catch((error) => { 58 | console.error(error); 59 | process.exitCode = 1; 60 | }); 61 | -------------------------------------------------------------------------------- /launchpad/scripts/add_staking_token.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | 4 | let WMNT; 5 | let AGNI; 6 | 7 | async function main() { 8 | const networkName = await network.name; 9 | console.log("Network name=", networkName); 10 | 11 | let contractAddresses = utils.getContractAddresses(networkName,""); 12 | 13 | if (networkName == "mantleMainnet") { 14 | WMNT = "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"; 15 | AGNI = ""; 16 | } else { 17 | WMNT = "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF"; 18 | AGNI = "0x113667C49c053230D3232AC7d74F471Dcd42f11E"; 19 | } 20 | console.log("WMNT addresses:", WMNT); 21 | 22 | const [owner, keeper] = await ethers.getSigners(); 23 | 24 | const StakingPool = await ethers.getContractFactory("StakingPool"); 25 | const stakingPool = await StakingPool.attach(contractAddresses.StakingPool); 26 | 27 | const ScoreCalculator = await ethers.getContractFactory("ScoreCalculator"); 28 | const scoreCalculator = await ScoreCalculator.attach( 29 | contractAddresses.ScoreCalculator.Proxy 30 | ); 31 | 32 | // add agni 33 | let agniIsStakingToken = await stakingPool.isStakingToken(WMNT); 34 | if (!agniIsStakingToken){ 35 | let addTx = await stakingPool.addStakingToken(WMNT); 36 | console.log("addStakingToken:", addTx.hash); 37 | } 38 | 39 | let scoreAgni = await scoreCalculator.agniToken(); 40 | console.log("score agni token:", scoreAgni); 41 | 42 | if (scoreAgni != WMNT) { 43 | let setAgniTokenTx = await scoreCalculator.setAgniToken(WMNT); 44 | console.log("setAgniTokenTx :", setAgniTokenTx.hash); 45 | } 46 | 47 | // add LP 48 | /*let agniMntFee100Lp = await scoreCalculator.isPoolSupported(AGNI, WMNT,100); 49 | console.log("scoreCalculator isPoolSupported:", agniMntFee100Lp); 50 | if (!agniMntFee100Lp){ 51 | let addAgniMntFee100LpTx = await scoreCalculator.supportPool(AGNI,WMNT,100); 52 | console.log("addAgniMntFee100LpTx:", addAgniMntFee100LpTx.hash); 53 | }*/ 54 | } 55 | 56 | // We recommend this pattern to be able to use async/await everywhere 57 | // and properly handle errors. 58 | main().catch((error) => { 59 | console.error(error); 60 | process.exitCode = 1; 61 | }); 62 | -------------------------------------------------------------------------------- /launchpad/scripts/add_staking_token copy.ts: -------------------------------------------------------------------------------- 1 | import { ethers,network } from "hardhat"; 2 | const utils = require("../../common/utils"); 3 | 4 | let WMNT; 5 | let AGNI; 6 | 7 | async function main() { 8 | const networkName = await network.name; 9 | console.log("Network name=", networkName); 10 | 11 | let contractAddresses = utils.getContractAddresses(networkName,""); 12 | 13 | if (networkName == "mantleMainnet") { 14 | WMNT = "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"; 15 | AGNI = ""; 16 | } else { 17 | WMNT = "0x67A1f4A939b477A6b7c5BF94D97E45dE87E608eF"; 18 | AGNI = "0x113667C49c053230D3232AC7d74F471Dcd42f11E"; 19 | } 20 | console.log("WMNT addresses:", WMNT); 21 | 22 | const [owner, keeper] = await ethers.getSigners(); 23 | 24 | const StakingPool = await ethers.getContractFactory("StakingPool"); 25 | const stakingPool = await StakingPool.attach(contractAddresses.StakingPool); 26 | 27 | const ScoreCalculator = await ethers.getContractFactory("ScoreCalculator"); 28 | const scoreCalculator = await ScoreCalculator.attach( 29 | contractAddresses.ScoreCalculator.Proxy 30 | ); 31 | 32 | // add agni 33 | let agniIsStakingToken = await stakingPool.isStakingToken(AGNI); 34 | if (!agniIsStakingToken){ 35 | let addTx = await stakingPool.addStakingToken(AGNI); 36 | console.log("addStakingToken:", addTx.hash); 37 | } 38 | 39 | let scoreAgni = await scoreCalculator.agniToken(); 40 | console.log("score agni token:", scoreAgni); 41 | 42 | if (scoreAgni == "0x0000000000000000000000000000000000000000") { 43 | let setAgniTokenTx = await scoreCalculator.setAgniToken(AGNI); 44 | console.log("setAgniTokenTx :", setAgniTokenTx.hash); 45 | } 46 | 47 | // add LP 48 | let agniMntFee100Lp = await scoreCalculator.isPoolSupported(AGNI, WMNT,100); 49 | console.log("scoreCalculator isPoolSupported:", agniMntFee100Lp); 50 | if (!agniMntFee100Lp){ 51 | let addAgniMntFee100LpTx = await scoreCalculator.supportPool(AGNI,WMNT,100); 52 | console.log("addAgniMntFee100LpTx:", addAgniMntFee100LpTx.hash); 53 | } 54 | } 55 | 56 | // We recommend this pattern to be able to use async/await everywhere 57 | // and properly handle errors. 58 | main().catch((error) => { 59 | console.error(error); 60 | process.exitCode = 1; 61 | }); 62 | -------------------------------------------------------------------------------- /periphery/contracts/base/SelfPermit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; 5 | import '@openzeppelin/contracts/drafts/IERC20Permit.sol'; 6 | 7 | import '../interfaces/ISelfPermit.sol'; 8 | import '../interfaces/external/IERC20PermitAllowed.sol'; 9 | 10 | /// @title Self Permit 11 | /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route 12 | /// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function 13 | /// that requires an approval in a single transaction. 14 | abstract contract SelfPermit is ISelfPermit { 15 | /// @inheritdoc ISelfPermit 16 | function selfPermit( 17 | address token, 18 | uint256 value, 19 | uint256 deadline, 20 | uint8 v, 21 | bytes32 r, 22 | bytes32 s 23 | ) public payable override { 24 | IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s); 25 | } 26 | 27 | /// @inheritdoc ISelfPermit 28 | function selfPermitIfNecessary( 29 | address token, 30 | uint256 value, 31 | uint256 deadline, 32 | uint8 v, 33 | bytes32 r, 34 | bytes32 s 35 | ) external payable override { 36 | if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s); 37 | } 38 | 39 | /// @inheritdoc ISelfPermit 40 | function selfPermitAllowed( 41 | address token, 42 | uint256 nonce, 43 | uint256 expiry, 44 | uint8 v, 45 | bytes32 r, 46 | bytes32 s 47 | ) public payable override { 48 | IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s); 49 | } 50 | 51 | /// @inheritdoc ISelfPermit 52 | function selfPermitAllowedIfNecessary( 53 | address token, 54 | uint256 nonce, 55 | uint256 expiry, 56 | uint8 v, 57 | bytes32 r, 58 | bytes32 s 59 | ) external payable override { 60 | if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max) 61 | selfPermitAllowed(token, nonce, expiry, v, r, s); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lm-pool/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from "hardhat/config"; 2 | import "@nomicfoundation/hardhat-toolbox"; 3 | import "@nomiclabs/hardhat-etherscan"; 4 | import "@openzeppelin/hardhat-upgrades"; 5 | import "hardhat-gas-reporter"; 6 | import "hardhat-contract-sizer"; 7 | import dotenv from "dotenv"; 8 | dotenv.config(); 9 | 10 | const config: HardhatUserConfig = { 11 | solidity: { 12 | compilers: [ 13 | { 14 | version: "0.7.6", 15 | settings: { 16 | optimizer: { 17 | enabled: true, 18 | runs: 200, 19 | }, 20 | }, 21 | }, 22 | ], 23 | }, 24 | networks: { 25 | mantleTestnet: { 26 | url: process.env.MANTLE_TESTNET_URL || "", 27 | accounts: 28 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 29 | }, 30 | mantleMainnet: { 31 | url: process.env.MANTLE_URL || "", 32 | accounts: 33 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 34 | }, 35 | mantleSepoliaTestnet: { 36 | url: process.env.MANTLE_SEPOLIA_TESTNET_URL || "", 37 | gasPrice: 50000000000, 38 | accounts: 39 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 40 | }, 41 | }, 42 | gasReporter: { 43 | enabled: process.env.REPORT_GAS !== undefined, 44 | currency: "USD", 45 | }, 46 | etherscan: { 47 | apiKey: process.env.MANTLESCAN_API_KEY, 48 | customChains: [ 49 | { 50 | network: "mantleTestnet", 51 | chainId: 5001, 52 | urls: { 53 | apiURL: "https://explorer.testnet.mantle.xyz/api", 54 | browserURL: "https://rpc.testnet.mantle.xyz", 55 | }, 56 | }, 57 | { 58 | network: "mantleSepoliaTestnet", 59 | chainId: 5003, 60 | urls: { 61 | apiURL: "https://explorer.sepolia.mantle.xyz/api", 62 | browserURL: "https://explorer.sepolia.mantle.xyz/", 63 | }, 64 | }, 65 | { 66 | network: "mantleMainnet", 67 | chainId: 5000, 68 | urls: { 69 | apiURL: "https://explorer.mantle.xyz/api", 70 | browserURL: "https://explorer.mantle.xyz/", 71 | }, 72 | }, 73 | ], 74 | }, 75 | }; 76 | 77 | export default config; 78 | --------------------------------------------------------------------------------