diff --git a/examples/05-invest-aave-idle-balance/manifest.yaml b/examples/05-invest-aave-idle-balance/manifest.yaml index 697a3cb..e7f7059 100644 --- a/examples/05-invest-aave-idle-balance/manifest.yaml +++ b/examples/05-invest-aave-idle-balance/manifest.yaml @@ -1,5 +1,5 @@ version: 1.0.0 -name: Invest in a AAVE idle balance +name: Invest in AAVE idle balance description: Automated task to invest in AAVE idle balance above certain threshold in USD inputs: - chainId: uint32 diff --git a/examples/13-bridge-and-invest-aave/.env.sample b/examples/13-bridge-and-invest-aave/.env.sample new file mode 100644 index 0000000..925d0ca --- /dev/null +++ b/examples/13-bridge-and-invest-aave/.env.sample @@ -0,0 +1,3 @@ +PRIVATE_KEY= +INVEST_CID= +SMART_ACCOUNT= diff --git a/examples/13-bridge-and-invest-aave/eslint.config.mjs b/examples/13-bridge-and-invest-aave/eslint.config.mjs new file mode 100644 index 0000000..90af2c8 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/eslint.config.mjs @@ -0,0 +1,89 @@ +import eslintPluginTypeScript from "@typescript-eslint/eslint-plugin" +import eslintParserTypeScript from "@typescript-eslint/parser" +import eslintPluginImport from "eslint-plugin-import" +import eslintPluginSimpleImportSort from "eslint-plugin-simple-import-sort" +import eslintConfigPrettier from "eslint-config-prettier" +import eslintPluginPrettier from "eslint-plugin-prettier" + +export default [ + { + ignores: ["node_modules/**", "**/dist/**", "**/build/**", "**/.prettierrc.*", "./src/types/**"] + }, + { + files: ["**/*.{ts,tsx}"], + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + parser: eslintParserTypeScript, + parserOptions: { + project: "./tsconfig.json" + } + }, + plugins: { + "@typescript-eslint": eslintPluginTypeScript, + prettier: eslintPluginPrettier, + import: eslintPluginImport, + "simple-import-sort": eslintPluginSimpleImportSort + }, + rules: { + ...eslintPluginTypeScript.configs.recommended.rules, + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-unused-vars": ["error"], + "@typescript-eslint/explicit-function-return-type": "error", + "@typescript-eslint/no-explicit-any": "error", + + "prettier/prettier": [ + "error", + { + "semi": false, + "singleQuote": true, + "trailingComma": "es5", + "arrowParens": "always", + "bracketSpacing": true, + "printWidth": 120, + "tabWidth": 2, + "useTabs": false + } + ], + + "simple-import-sort/imports": [ + "error", + { + groups: [ + ["^@?\\w"], + ["^\\.\\.(?!/?$)", "^\\.\\./?$"], + ["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"] + ] + } + ], + "simple-import-sort/exports": "error", + + "comma-spacing": ["error", { before: false, after: true }], + "no-multiple-empty-lines": ["error", { max: 1, maxEOF: 1 }] + }, + settings: { + "import/resolver": { + typescript: { + alwaysTryTypes: true, + project: "./tsconfig.json" + } + } + } + }, + // configuration for test files + { + files: ["tests/**/*.{ts,tsx}", "**/*.spec.{ts,tsx}", "**/*.test.{ts,tsx}"], + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + parser: eslintParserTypeScript, + parserOptions: { + project: "./tests/tsconfig.json" + } + }, + rules: { + "@typescript-eslint/no-unused-expressions": "off" + } + }, + eslintConfigPrettier +] \ No newline at end of file diff --git a/examples/13-bridge-and-invest-aave/manifest.bridge.yaml b/examples/13-bridge-and-invest-aave/manifest.bridge.yaml new file mode 100644 index 0000000..17c7ea8 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/manifest.bridge.yaml @@ -0,0 +1,11 @@ +version: 1.0.0 +name: Bridge USDC and emit an event +description: Bridge USDC between Arbitrum, Base and Optimism, and emit a custom event to trigger another task +inputs: + - sourceChain: uint32 + - destinationChain: uint32 + - smartAccount: address # Important: The smart account should exist in both chains + - amount: string + - minAmountOut: string + - feeToken: address + - maxFee: string diff --git a/examples/13-bridge-and-invest-aave/manifest.invest.yaml b/examples/13-bridge-and-invest-aave/manifest.invest.yaml new file mode 100644 index 0000000..481c5ab --- /dev/null +++ b/examples/13-bridge-and-invest-aave/manifest.invest.yaml @@ -0,0 +1,12 @@ +version: 1.0.0 +name: Deposit USDC in Aave (event trigger) +description: Deposit in Aave USDC tokens that were bridged from another chain +inputs: + - chainId: uint32 + - smartAccount: address + - feeToken: address + - maxFee: string +abis: + - AavePool: ./src/abis/AavePool.json + - ERC20: ./src/abis/ERC20.json + - Settler: ./src/abis/Settler.json diff --git a/examples/13-bridge-and-invest-aave/package.json b/examples/13-bridge-and-invest-aave/package.json new file mode 100644 index 0000000..f031201 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/package.json @@ -0,0 +1,43 @@ +{ + "name": "@mimicprotocol/13-bridge-and-invest-aave", + "version": "0.0.1", + "license": "Unlicensed", + "private": true, + "type": "module", + "scripts": { + "build": "yarn codegen && yarn compile", + "codegen": "yarn codegen:bridge && yarn codegen:invest", + "codegen:bridge": "yarn mimic codegen -m manifest.bridge.yaml -o ./src/types/bridge", + "codegen:invest": "yarn mimic codegen -m manifest.invest.yaml -o ./src/types/invest", + "compile": "yarn compile:bridge && yarn compile:invest", + "compile:bridge": "mimic compile -t src/bridge.ts -m manifest.bridge.yaml -o ./build/bridge", + "compile:invest": "mimic compile -t src/invest.ts -m manifest.invest.yaml -o ./build/invest", + "deploy:bridge": "yarn codegen:bridge && yarn compile:bridge && mimic deploy --input ./build/bridge --output ./build/bridge --skip-compile", + "deploy:invest": "yarn codegen:invest && yarn compile:invest && mimic deploy --input ./build/invest --output ./build/invest --skip-compile", + "test": "yarn build && mimic test --skipCompile", + "create-config:invest": "tsc -p tsconfig.create-config.json && tsx src/create-config.invest.ts", + "lint": "eslint ." + }, + "dependencies": { + "dotenv": "^17.0.0", + "ethers": "^6.13.5", + "semver": "^7.7.3" + }, + "devDependencies": { + "@mimicprotocol/cli": "latest", + "@mimicprotocol/lib-ts": "latest", + "@mimicprotocol/sdk": "latest", + "@mimicprotocol/test-ts": "latest", + "@types/chai": "^5.2.2", + "@types/mocha": "^10.0.10", + "@types/node": "^22.10.5", + "assemblyscript": "0.27.36", + "chai": "^4.3.7", + "eslint": "^9.10.0", + "json-as": "1.1.7", + "mocha": "^10.2.0", + "tsx": "^4.20.3", + "typescript": "^5.8.3", + "visitor-as": "0.11.4" + } +} \ No newline at end of file diff --git a/examples/13-bridge-and-invest-aave/src/abis/AavePool.json b/examples/13-bridge-and-invest-aave/src/abis/AavePool.json new file mode 100644 index 0000000..4a8d2fc --- /dev/null +++ b/examples/13-bridge-and-invest-aave/src/abis/AavePool.json @@ -0,0 +1,2277 @@ +[ + { + "inputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "provider", + "type": "address" + }, + { + "internalType": "contract IReserveInterestRateStrategy", + "name": "interestRateStrategy_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "AssetNotListed", + "type": "error" + }, + { + "inputs": [], + "name": "CallerNotAToken", + "type": "error" + }, + { + "inputs": [], + "name": "CallerNotPoolAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "CallerNotPoolConfigurator", + "type": "error" + }, + { + "inputs": [], + "name": "CallerNotPositionManager", + "type": "error" + }, + { + "inputs": [], + "name": "CallerNotUmbrella", + "type": "error" + }, + { + "inputs": [], + "name": "EModeCategoryReserved", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddressesProvider", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotValid", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum DataTypes.InterestRateMode", + "name": "interestRateMode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountCovered", + "type": "uint256" + } + ], + "name": "DeficitCovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountCreated", + "type": "uint256" + } + ], + "name": "DeficitCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum DataTypes.InterestRateMode", + "name": "interestRateMode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "premium", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDebt", + "type": "uint256" + } + ], + "name": "IsolationModeTotalDebtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "collateralAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "debtToCover", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidatedCollateralAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "receiveAToken", + "type": "bool" + } + ], + "name": "LiquidationCall", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountMinted", + "type": "uint256" + } + ], + "name": "MintedToTreasury", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "positionManager", + "type": "address" + } + ], + "name": "PositionManagerApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "positionManager", + "type": "address" + } + ], + "name": "PositionManagerRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "useATokens", + "type": "bool" + } + ], + "name": "Repay", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidityRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stableBorrowRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "variableBorrowRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidityIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "variableBorrowIndex", + "type": "uint256" + } + ], + "name": "ReserveDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ReserveUsedAsCollateralDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ReserveUsedAsCollateralEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "Supply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "categoryId", + "type": "uint8" + } + ], + "name": "UserEModeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "reserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "ADDRESSES_PROVIDER", + "outputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FLASHLOAN_PREMIUM_TOTAL", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FLASHLOAN_PREMIUM_TO_PROTOCOL", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUMBER_RESERVES", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "POOL_REVISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESERVE_INTEREST_RATE_STRATEGY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UMBRELLA", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "positionManager", + "type": "address" + }, + { + "internalType": "bool", + "name": "approve", + "type": "bool" + } + ], + "name": "approvePositionManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + } + ], + "name": "borrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + } + ], + "name": "borrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "ltv", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationThreshold", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationBonus", + "type": "uint16" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "internalType": "struct DataTypes.EModeCategoryBaseConfiguration", + "name": "category", + "type": "tuple" + } + ], + "name": "configureEModeCategory", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "internalType": "uint128", + "name": "borrowableBitmap", + "type": "uint128" + } + ], + "name": "configureEModeCategoryBorrowableBitmap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "internalType": "uint128", + "name": "collateralBitmap", + "type": "uint128" + } + ], + "name": "configureEModeCategoryCollateralBitmap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "dropReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "eliminateReserveDeficit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceFromBefore", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceToBefore", + "type": "uint256" + } + ], + "name": "finalizeTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiverAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "interestRateModes", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "flashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiverAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "flashLoanSimple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBorrowLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getConfiguration", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.ReserveConfigurationMap", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + } + ], + "name": "getEModeCategoryBorrowableBitmap", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + } + ], + "name": "getEModeCategoryCollateralBitmap", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + } + ], + "name": "getEModeCategoryCollateralConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "ltv", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationThreshold", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationBonus", + "type": "uint16" + } + ], + "internalType": "struct DataTypes.CollateralConfig", + "name": "res", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + } + ], + "name": "getEModeCategoryData", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "ltv", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationThreshold", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "liquidationBonus", + "type": "uint16" + }, + { + "internalType": "address", + "name": "priceSource", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "internalType": "struct DataTypes.EModeCategoryLegacy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "id", + "type": "uint8" + } + ], + "name": "getEModeCategoryLabel", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEModeLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFlashLoanLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getLiquidationGracePeriod", + "outputs": [ + { + "internalType": "uint40", + "name": "", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLiquidationLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPoolLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveAToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "id", + "type": "uint16" + } + ], + "name": "getReserveAddressById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveData", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.ReserveConfigurationMap", + "name": "configuration", + "type": "tuple" + }, + { + "internalType": "uint128", + "name": "liquidityIndex", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "currentLiquidityRate", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "variableBorrowIndex", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "currentVariableBorrowRate", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "currentStableBorrowRate", + "type": "uint128" + }, + { + "internalType": "uint40", + "name": "lastUpdateTimestamp", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "id", + "type": "uint16" + }, + { + "internalType": "address", + "name": "aTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "stableDebtTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "variableDebtTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "interestRateStrategyAddress", + "type": "address" + }, + { + "internalType": "uint128", + "name": "accruedToTreasury", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "unbacked", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "isolationModeTotalDebt", + "type": "uint128" + } + ], + "internalType": "struct DataTypes.ReserveDataLegacy", + "name": "res", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveDeficit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveNormalizedIncome", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveNormalizedVariableDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getReserveVariableDebtToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getReservesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getReservesList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSupplyLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserAccountData", + "outputs": [ + { + "internalType": "uint256", + "name": "totalCollateralBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalDebtBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableBorrowsBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentLiquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ltv", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "healthFactor", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserConfiguration", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.UserConfigurationMap", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserEMode", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVirtualUnderlyingBalance", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "aTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "variableDebtAddress", + "type": "address" + } + ], + "name": "initReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPoolAddressesProvider", + "name": "provider", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "positionManager", + "type": "address" + } + ], + "name": "isApprovedPositionManager", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collateralAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "debtAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "debtToCover", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "receiveAToken", + "type": "bool" + } + ], + "name": "liquidationCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "args2", + "type": "bytes32" + } + ], + "name": "liquidationCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + } + ], + "name": "mintToTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "renouncePositionManagerRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + } + ], + "name": "repay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + } + ], + "name": "repay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + } + ], + "name": "repayWithATokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + } + ], + "name": "repayWithATokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "repayWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "interestRateMode", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "permitV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "permitR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "permitS", + "type": "bytes32" + } + ], + "name": "repayWithPermit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "resetIsolationModeTotalDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "internalType": "struct DataTypes.ReserveConfigurationMap", + "name": "configuration", + "type": "tuple" + } + ], + "name": "setConfiguration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint40", + "name": "until", + "type": "uint40" + } + ], + "name": "setLiquidationGracePeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "categoryId", + "type": "uint8" + } + ], + "name": "setUserEMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "categoryId", + "type": "uint8" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + } + ], + "name": "setUserEModeOnBehalfOf", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + } + ], + "name": "setUserUseReserveAsCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "useAsCollateral", + "type": "bool" + } + ], + "name": "setUserUseReserveAsCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "useAsCollateral", + "type": "bool" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + } + ], + "name": "setUserUseReserveAsCollateralOnBehalfOf", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + } + ], + "name": "supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + } + ], + "name": "supply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "onBehalfOf", + "type": "address" + }, + { + "internalType": "uint16", + "name": "referralCode", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "permitV", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "permitR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "permitS", + "type": "bytes32" + } + ], + "name": "supplyWithPermit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "supplyWithPermit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "syncIndexesState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "syncRatesState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "flashLoanPremium", + "type": "uint128" + } + ], + "name": "updateFlashloanPremium", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "args", + "type": "bytes32" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/examples/13-bridge-and-invest-aave/src/abis/ERC20.json b/examples/13-bridge-and-invest-aave/src/abis/ERC20.json new file mode 100644 index 0000000..405d6b3 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/src/abis/ERC20.json @@ -0,0 +1,222 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] diff --git a/examples/13-bridge-and-invest-aave/src/abis/Settler.json b/examples/13-bridge-and-invest-aave/src/abis/Settler.json new file mode 100644 index 0000000..ee186a4 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/src/abis/Settler.json @@ -0,0 +1,1403 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_controller", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposed", + "type": "uint256" + } + ], + "name": "SettlerAmountOutLtProposed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "executor", + "type": "address" + } + ], + "name": "SettlerExecutorNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SettlerIntentPastDeadline", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "current", + "type": "uint256" + } + ], + "name": "SettlerIntentValidationsNotEnough", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "SettlerInvalidChain", + "type": "error" + }, + { + "inputs": [], + "name": "SettlerInvalidProposedAmounts", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SettlerInvalidRecipient", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "settler", + "type": "address" + } + ], + "name": "SettlerInvalidSettler", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + } + ], + "name": "SettlerNonceAlreadyUsed", + "type": "error" + }, + { + "inputs": [], + "name": "SettlerNonceZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "post", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pre", + "type": "uint256" + } + ], + "name": "SettlerPostBalanceOutLtPre", + "type": "error" + }, + { + "inputs": [], + "name": "SettlerProposalDataNotEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SettlerProposalPastDeadline", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "SettlerProposalSignerNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proposed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minAmount", + "type": "uint256" + } + ], + "name": "SettlerProposedAmountLtMinAmount", + "type": "error" + }, + { + "inputs": [], + "name": "SettlerRescueFundsRecipientZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "name": "SettlerSimulationSuccess", + "type": "error" + }, + { + "inputs": [], + "name": "SettlerSolverFeeInvalidLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "SettlerSolverFeeTooHigh", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "solver", + "type": "address" + } + ], + "name": "SettlerSolverNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "lengthRequested", + "type": "uint256" + } + ], + "name": "SettlerTooManySafeguards", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "op", + "type": "uint8" + } + ], + "name": "SettlerUnknownIntentType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "SettlerUserNotSmartAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previous", + "type": "address" + }, + { + "internalType": "address", + "name": "current", + "type": "address" + } + ], + "name": "SettlerValidatorDuplicatedOrUnsorted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "SettlerValidatorNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "SmartAccountsHandlerZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRescued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "topic", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "op", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "op", + "type": "uint8" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "settler", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct MaxFee[]", + "name": "maxFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "topic", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct IntentEvent[]", + "name": "events", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "configSig", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "minValidations", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "validations", + "type": "bytes[]" + } + ], + "indexed": false, + "internalType": "struct Intent", + "name": "intent", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + } + ], + "indexed": false, + "internalType": "struct Proposal", + "name": "proposal", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "output", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "IntentExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "intentsValidator", + "type": "address" + } + ], + "name": "IntentsValidatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "proposal", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "ProposalExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "SafeguardSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "smartAccountsHandler", + "type": "address" + } + ], + "name": "SmartAccountsHandlerSet", + "type": "event" + }, + { + "inputs": [], + "name": "controller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint8", + "name": "op", + "type": "uint8" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "settler", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct MaxFee[]", + "name": "maxFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "topic", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct IntentEvent[]", + "name": "events", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "configSig", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "minValidations", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "validations", + "type": "bytes[]" + } + ], + "internalType": "struct Intent", + "name": "intent", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + } + ], + "internalType": "struct Proposal", + "name": "proposal", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct Execution[]", + "name": "executions", + "type": "tuple[]" + } + ], + "name": "execute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "op", + "type": "uint8" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "settler", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct MaxFee[]", + "name": "maxFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "topic", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct IntentEvent[]", + "name": "events", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "configSig", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "minValidations", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "validations", + "type": "bytes[]" + } + ], + "internalType": "struct Intent", + "name": "intent", + "type": "tuple" + } + ], + "name": "getIntentHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "getNonceBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + } + ], + "internalType": "struct Proposal", + "name": "proposal", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "op", + "type": "uint8" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "settler", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct MaxFee[]", + "name": "maxFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "topic", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct IntentEvent[]", + "name": "events", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "configSig", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "minValidations", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "validations", + "type": "bytes[]" + } + ], + "internalType": "struct Intent", + "name": "intent", + "type": "tuple" + }, + { + "internalType": "address", + "name": "solver", + "type": "address" + } + ], + "name": "getProposalHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserSafeguard", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "intentsValidator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newIntentsValidator", + "type": "address" + } + ], + "name": "setIntentsValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "safeguard", + "type": "bytes" + } + ], + "name": "setSafeguard", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newSmartAccountsHandler", + "type": "address" + } + ], + "name": "setSmartAccountsHandler", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint8", + "name": "op", + "type": "uint8" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "settler", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct MaxFee[]", + "name": "maxFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "topic", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct IntentEvent[]", + "name": "events", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "configSig", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "minValidations", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "validations", + "type": "bytes[]" + } + ], + "internalType": "struct Intent", + "name": "intent", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "fees", + "type": "uint256[]" + } + ], + "internalType": "struct Proposal", + "name": "proposal", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct Execution[]", + "name": "executions", + "type": "tuple[]" + } + ], + "name": "simulate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "smartAccountsHandler", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] \ No newline at end of file diff --git a/examples/13-bridge-and-invest-aave/src/bridge.ts b/examples/13-bridge-and-invest-aave/src/bridge.ts new file mode 100644 index 0000000..e68ad25 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/src/bridge.ts @@ -0,0 +1,52 @@ +import { + Arbitrum, + Base, + Bytes, + ChainId, + ERC20Token, + evm, + EvmEncodeParam, + Optimism, + SwapBuilder, + Token, + TokenAmount, +} from '@mimicprotocol/lib-ts' + +import { inputs } from './types/bridge' + +export default function main(): void { + const sourceChain = inputs.sourceChain + const destinationChain = inputs.destinationChain + if (sourceChain == destinationChain) throw new Error('Single-chain swap not supported') + + const tokenIn = getUsdc(sourceChain) + const tokenAmountIn = TokenAmount.fromStringDecimal(tokenIn, inputs.amount) + + const tokenOut = getUsdc(destinationChain) + const tokenAmountOut = TokenAmount.fromStringDecimal(tokenOut, inputs.minAmountOut) + + const feeToken = new ERC20Token(inputs.feeToken, inputs.destinationChain) + const maxFee = TokenAmount.fromStringDecimal(feeToken, inputs.maxFee) + + // Set topic hash and encode tokenOut address as extra data + const topic = evm.keccak('Bridged USDC') + const data = evm.encode([EvmEncodeParam.fromValue('address', tokenAmountOut.token.address)]) + + // Bridge tokens owned by the smart account + SwapBuilder.forChains(sourceChain, destinationChain) + .addTokenInFromTokenAmount(tokenAmountIn) + .addTokenOutFromTokenAmount(tokenAmountOut, inputs.smartAccount) + .addUser(inputs.smartAccount) + .addMaxFee(maxFee) + // Settler smart contract will emit an IntentExecuted event in which `topic2 = keccak256('Bridged USDC')` + .addEvent(Bytes.fromHexString(topic), Bytes.fromHexString(data)) // Optional + .build() + .send() +} + +function getUsdc(chainId: i32): Token { + if (chainId == ChainId.ARBITRUM) return Arbitrum.USDC + if (chainId == ChainId.BASE) return Base.USDC + if (chainId == ChainId.OPTIMISM) return Optimism.USDC + throw new Error('Invalid chain') +} diff --git a/examples/13-bridge-and-invest-aave/src/create-config.invest.ts b/examples/13-bridge-and-invest-aave/src/create-config.invest.ts new file mode 100644 index 0000000..c8ee3bd --- /dev/null +++ b/examples/13-bridge-and-invest-aave/src/create-config.invest.ts @@ -0,0 +1,84 @@ +import { config } from 'dotenv' +config() + +import { Chains, Client, EthersSigner, Sort, TriggerType } from '@mimicprotocol/sdk' +import { AbiCoder, Interface, keccak256, toUtf8Bytes, Wallet } from 'ethers' +import { inc } from 'semver' + +import SettlerAbi from './abis/Settler.json' + +const SETTLER_IFACE = new Interface(SettlerAbi) +const INTENT_EXECUTED_TOPIC = SETTLER_IFACE.getEvent('IntentExecuted')!.topicHash +const BRIDGED_TOPIC = keccak256(toUtf8Bytes('Bridged USDC')) + +const MIMIC_PROTOCOL_SETTLER = '0x609d831C0068844e11eF85a273c7F356212Fd6D1' + +const USDT: Record = { + 10: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', // Optimism + 8453: '0xfde4c96c8593536e31f229ea8f37b2ada2699bb2', // Base + 42161: '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', // Arbitrum +} + +async function main(): Promise { + if (!process.env.PRIVATE_KEY) throw new Error('Missing PRIVATE_KEY in .env file') + if (!process.env.INVEST_CID) throw new Error('Missing INVEST_CID in .env file') + if (!process.env.SMART_ACCOUNT) throw new Error('Missing SMART_ACCOUNT in .env file') + const { PRIVATE_KEY, INVEST_CID, SMART_ACCOUNT } = process.env + + // Create client with signer + const signer = EthersSigner.fromPrivateKey(PRIVATE_KEY) + const client = new Client({ signer }) + + // Get task manifest from deployed task + const manifest = await client.tasks.getManifest(INVEST_CID) + + // Set user topic to filter events + const USER_TOPIC = AbiCoder.defaultAbiCoder().encode(['address'], [SMART_ACCOUNT]) + + // Increment config version + const latestConfig = await client.configs.get({ taskCid: INVEST_CID, sort: Sort.desc, limit: 1 }) + const version = latestConfig.length > 0 ? inc(latestConfig[0].version.split('-')[0], 'patch') : '0.0.1' + if (!version) throw new Error('Invalid config version') + + // Set trigger based on a blockchain event + const trigger = { + type: TriggerType.Event as const, + contract: MIMIC_PROTOCOL_SETTLER, + topics: [ + [INTENT_EXECUTED_TOPIC], // The event emitted by the Settler + [USER_TOPIC], // Important: To prevent other users from triggering this task + [BRIDGED_TOPIC], // Emitted by the bridge task + ], + delta: '1h', + endDate: 0, // No end date + } + + // Submit one task config per chain + const chainIds = [Chains.Arbitrum, Chains.Base, Chains.Optimism] + for (const chainId of chainIds) { + const input = { + chainId, + smartAccount: SMART_ACCOUNT, + feeToken: USDT[chainId], + maxFee: '0.3', + } + + const config = await client.configs.signAndCreate({ + description: `Invest bridged amount in Aave (${chainId})`, + taskCid: INVEST_CID, + version: `${version}-${chainId}`, + manifest, + trigger: { ...trigger, chainId }, + input, + executionFeeLimit: '0', + minValidations: 1, + signer: new Wallet(PRIVATE_KEY).address, + }) + console.log(`Created config on chain ${chainId}: ${config.sig}`) + } +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/examples/13-bridge-and-invest-aave/src/invest.ts b/examples/13-bridge-and-invest-aave/src/invest.ts new file mode 100644 index 0000000..d91ed49 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/src/invest.ts @@ -0,0 +1,63 @@ +import { + Address, + BigInt, + ChainId, + environment, + ERC20Token, + evm, + EvmCallBuilder, + EvmDecodeParam, + JSON, + TokenAmount, + TriggerType, +} from '@mimicprotocol/lib-ts' + +import { inputs } from './types/invest' +import { AavePoolUtils } from './types/invest/AavePool' +import { ERC20Utils } from './types/invest/ERC20' +import { IntentExecutedEvent } from './types/invest/Settler' + +export default function main(): void { + const chainId = inputs.chainId + const smartAccount = inputs.smartAccount + + const aaveV3Pool = getAaveV3Pool(chainId) + + const trigger = environment.getContext().trigger + if (trigger.type != TriggerType.EVENT) throw new Error('Trigger not event') + + const triggerData = trigger.getEventData() + const event = IntentExecutedEvent.decode(triggerData.topics, triggerData.eventData) + if (event.intent.user != smartAccount) throw new Error('Intent user not smart account') + + // Get the token and the amount from the event emitted by the task that triggered this one + const tokenStr = evm.decode(new EvmDecodeParam('address', event.data.toHexString())) + const token = Address.fromString(tokenStr) + + const amountsStr = evm.decode(new EvmDecodeParam('uint256[]', event.output.toHexString())) + const amounts = JSON.parse(amountsStr) + if (amounts.length == 0) throw new Error('Empty amounts array') + const amount = BigInt.fromString(amounts[0]) + + const feeToken = new ERC20Token(inputs.feeToken, chainId) + const maxFee = TokenAmount.fromStringDecimal(feeToken, inputs.maxFee) + + const approveData = ERC20Utils.encodeApprove(aaveV3Pool, amount) + const supplyData = AavePoolUtils.encodeSupply(token, amount, smartAccount, 0) + + // Give approval and deposit the tokens, owned by the smart account + EvmCallBuilder.forChain(chainId) + .addCall(token, approveData) + .addCall(aaveV3Pool, supplyData) + .addUser(smartAccount) + .addMaxFee(maxFee) + .build() + .send() +} + +function getAaveV3Pool(chainId: i32): Address { + if (chainId == ChainId.ARBITRUM) return Address.fromString('0x794a61358d6845594f94dc1db02a252b5b4814ad') + if (chainId == ChainId.BASE) return Address.fromString('0xa238dd80c259a72e81d7e4664a9801593f98d1c5') + if (chainId == ChainId.OPTIMISM) return Address.fromString('0x794a61358d6845594f94dc1db02a252b5b4814ad') + throw new Error('Invalid chain') +} diff --git a/examples/13-bridge-and-invest-aave/tests/bridge.spec.ts b/examples/13-bridge-and-invest-aave/tests/bridge.spec.ts new file mode 100644 index 0000000..3b27c0e --- /dev/null +++ b/examples/13-bridge-and-invest-aave/tests/bridge.spec.ts @@ -0,0 +1,114 @@ +import { Chains, fp, OpType, randomEvmAddress } from '@mimicprotocol/sdk' +import { Context, ContractCallMock, Inputs, runTask, Swap } from '@mimicprotocol/test-ts' +import { expect } from 'chai' +import { AbiCoder, keccak256, toUtf8Bytes } from 'ethers' + +describe('Bridge', () => { + const taskDir = './build/bridge' + + const sourceChain = Chains.Arbitrum + const destinationChain = Chains.Optimism + const arbitrumUsdc = '0xaf88d065e77c8cc2239327c5edb3a432268e5831' + const optimismUsdc = '0x0b2c639c533813f4aa9d7837caf62653d097ff85' + const decimals = 6 + const settler = randomEvmAddress() + + const context: Context = { + user: randomEvmAddress(), + settlers: [ + { address: settler, chainId: sourceChain }, + { address: settler, chainId: destinationChain }, + ], + timestamp: Date.now(), + } + + const inputs = { + sourceChain, + destinationChain, + smartAccount: randomEvmAddress(), + amount: '10000', // 10,000 USDC + minAmountOut: '9990', // 9,990 USDC + feeToken: '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', // USDT on destination chain + maxFee: '0.5', // 0.5 USDT + } + + const calls: ContractCallMock[] = [ + { + request: { to: arbitrumUsdc, chainId: sourceChain, fnSelector: '0x313ce567' }, // `decimals` + response: { value: decimals.toString(), abiType: 'uint8' }, + }, + { + request: { to: optimismUsdc, chainId: destinationChain, fnSelector: '0x313ce567' }, // `decimals` + response: { value: decimals.toString(), abiType: 'uint8' }, + }, + { + request: { to: inputs.feeToken, chainId: destinationChain, fnSelector: '0x313ce567' }, // `decimals` + response: { value: decimals.toString(), abiType: 'uint8' }, + }, + ] + + const itThrowsAnError = (inputs: Inputs, error: string): void => { + it('throws an error', async () => { + const result = await runTask(taskDir, context, { inputs, calls }) + expect(result.success).to.be.false + expect(result.intents).to.have.lengthOf(0) + + expect(result.logs).to.have.lengthOf(1) + expect(result.logs[0]).to.include(error) + }) + } + + describe('when the chains are supported', () => { + describe('when the chains are different', () => { + it('produces the expected intents', async () => { + const result = await runTask(taskDir, context, { inputs, calls }) + expect(result.success).to.be.true + expect(result.timestamp).to.be.equal(context.timestamp) + + const intents = result.intents as Swap[] + expect(intents).to.have.lengthOf(1) + + expect(intents[0].op).to.be.equal(OpType.Swap) + expect(intents[0].settler).to.be.equal(context.settlers?.[0].address) + expect(intents[0].user).to.be.equal(inputs.smartAccount) + expect(intents[0].sourceChain).to.be.equal(sourceChain) + expect(intents[0].destinationChain).to.be.equal(destinationChain) + + const amount = fp(inputs.amount, decimals).toString() + expect(intents[0].tokensIn).to.have.lengthOf(1) + expect(intents[0].tokensIn[0].token).to.be.equal(arbitrumUsdc) + expect(intents[0].tokensIn[0].amount).to.be.equal(amount) + + const minAmountOut = fp(inputs.minAmountOut, decimals).toString() + expect(intents[0].tokensOut).to.have.lengthOf(1) + expect(intents[0].tokensOut[0].token).to.be.equal(optimismUsdc) + expect(intents[0].tokensOut[0].minAmount).to.be.equal(minAmountOut) + expect(intents[0].tokensOut[0].recipient).to.be.equal(inputs.smartAccount) + + expect(intents[0].maxFees).to.have.lengthOf(1) + expect(intents[0].maxFees[0].token).to.be.equal(inputs.feeToken) + expect(intents[0].maxFees[0].amount).to.be.equal(fp(inputs.maxFee, decimals).toString()) + + expect(intents[0].events).to.have.lengthOf(1) + + const topic = keccak256(toUtf8Bytes('Bridged USDC')) + expect(intents[0].events[0].topic).to.be.equal(topic) + + const data = AbiCoder.defaultAbiCoder().encode(['address'], [optimismUsdc]) + expect(intents[0].events[0].data).to.be.equal(data) + }) + }) + + describe('when the chains are the same', () => { + const inputsSameChain = { ...inputs, destinationChain: inputs.sourceChain } + + itThrowsAnError(inputsSameChain, 'Single-chain swap not supported') + }) + }) + + describe('when the chains are not supported', () => { + const inputsUnsupportedChain = { ...inputs, destinationChain: Chains.Mainnet } + + itThrowsAnError(inputsUnsupportedChain, 'Invalid chain') + }) +}) diff --git a/examples/13-bridge-and-invest-aave/tests/invest.spec.ts b/examples/13-bridge-and-invest-aave/tests/invest.spec.ts new file mode 100644 index 0000000..ef66a44 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/tests/invest.spec.ts @@ -0,0 +1,166 @@ +import { + Chains, + encodeEventExecution, + fp, + OpType, + randomEvmAddress, + randomHex, + randomSig, + TriggerType, +} from '@mimicprotocol/sdk' +import { Call, Context, ContractCallMock, Inputs, runTask } from '@mimicprotocol/test-ts' +import { expect } from 'chai' +import { AbiCoder, Interface } from 'ethers' + +import AavePool from '../src/abis/AavePool.json' +import ERC20Abi from '../src/abis/ERC20.json' +import SettlerAbi from '../src/abis/Settler.json' + +const ERC20Interface = new Interface(ERC20Abi) +const AavePoolInterface = new Interface(AavePool) +const SettlerInterface = new Interface(SettlerAbi) + +describe('Invest', () => { + const taskDir = './build/invest' + + const chainId = Chains.Optimism + const aavePool = '0x794a61358d6845594f94dc1db02a252b5b4814ad' + const USDC = randomEvmAddress() + const decimals = 6 + const amount = fp(10000, decimals) // 10,000 USDC + const settler = randomEvmAddress() + const smartAccount = randomEvmAddress() + + const encodedAmounts = AbiCoder.defaultAbiCoder().encode(['uint256[]'], [[amount]]) + const encodedToken = AbiCoder.defaultAbiCoder().encode(['address'], [USDC]) + const encodedEvent = encodeEvent(smartAccount, encodedAmounts, encodedToken) + const trigger = { + type: TriggerType.Event, + data: encodeEventExecution({ + blockHash: randomHex(32), + index: 0, + topics: encodedEvent.topics, + eventData: encodedEvent.data, + }), + } + + const context: Context = { + user: randomEvmAddress(), + settlers: [{ address: settler, chainId }], + timestamp: Date.now(), + trigger, + } + + const inputs = { + chainId, + smartAccount, + feeToken: randomEvmAddress(), + maxFee: '0.5', // 0.5 feeToken + } + + const calls: ContractCallMock[] = [ + { + request: { to: USDC, chainId, fnSelector: '0x313ce567' }, // `decimals` + response: { value: decimals.toString(), abiType: 'uint8' }, + }, + { + request: { to: inputs.feeToken, chainId, fnSelector: '0x313ce567' }, // `decimals` + response: { value: '18', abiType: 'uint8' }, + }, + ] + + const itThrowsAnError = (context: Context, inputs: Inputs, error: string): void => { + it('throws an error', async () => { + const result = await runTask(taskDir, context, { inputs, calls }) + expect(result.success).to.be.false + expect(result.intents).to.have.lengthOf(0) + + expect(result.logs).to.have.lengthOf(1) + expect(result.logs[0]).to.include(error) + }) + } + + describe('when the chain is supported', () => { + describe('when the trigger is event', () => { + describe('when the event user is the smart account', () => { + it('produces the expected intents', async () => { + const result = await runTask(taskDir, context, { inputs, calls }) + expect(result.success).to.be.true + expect(result.timestamp).to.be.equal(context.timestamp) + + const intents = result.intents as Call[] + expect(intents).to.have.lengthOf(1) + + expect(intents[0].op).to.be.equal(OpType.EvmCall) + expect(intents[0].settler).to.be.equal(context.settlers?.[0].address) + expect(intents[0].user).to.be.equal(inputs.smartAccount) + expect(intents[0].chainId).to.be.equal(inputs.chainId) + + expect(intents[0].maxFees).to.have.lengthOf(1) + expect(intents[0].maxFees[0].token).to.be.equal(inputs.feeToken) + expect(intents[0].maxFees[0].amount).to.be.equal(fp(inputs.maxFee).toString()) + + expect(intents[0].calls).to.have.lengthOf(2) + + const expectedApproveData = ERC20Interface.encodeFunctionData('approve', [aavePool, amount]) + expect(intents[0].calls[0].target).to.be.equal(USDC) + expect(intents[0].calls[0].value).to.be.equal('0') + expect(intents[0].calls[0].data).to.be.equal(expectedApproveData) + + const expectedSupplyData = AavePoolInterface.encodeFunctionData('supply(address,uint256,address,uint16)', [ + USDC, + amount, + smartAccount, + 0, + ]) + expect(intents[0].calls[1].target).to.be.equal(aavePool) + expect(intents[0].calls[1].value).to.be.equal('0') + expect(intents[0].calls[1].data).to.be.equal(expectedSupplyData) + }) + }) + + describe('when the event user is not the smart account', () => { + const inputsOtherSmartAccount = { ...inputs, smartAccount: randomEvmAddress() } + + itThrowsAnError(context, inputsOtherSmartAccount, 'Intent user not smart account') + }) + }) + + describe('when the trigger is not event', () => { + const cronContext = { ...context, trigger: { ...trigger, type: TriggerType.Cron } } + + itThrowsAnError(cronContext, inputs, 'Trigger not event') + }) + }) + + describe('when the chain is not supported', () => { + const inputsUnsupportedChain = { ...inputs, chainId: Chains.Mainnet } + + itThrowsAnError(context, inputsUnsupportedChain, 'Invalid chain') + }) +}) + +export function encodeEvent(user: string, output: string, data: string): { topics: string[]; data: string } { + const topic = randomHex(32) + const op = OpType.Swap + const intent = [ + op, + user, + randomEvmAddress(), // settler + randomHex(32), // nonce + '0', // deadline + '0x', // data + [], // maxFees + [], // events + randomSig(), // configSig + 0, // minValidations + [], // validations + ] + const proposal = [ + '0', // deadline + '0x', // executorData + [], // fees + ] + + return SettlerInterface.encodeEventLog('IntentExecuted', [user, topic, op, intent, proposal, output, data]) +} diff --git a/examples/13-bridge-and-invest-aave/tests/tsconfig.json b/examples/13-bridge-and-invest-aave/tests/tsconfig.json new file mode 100644 index 0000000..821e603 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/tests/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "declaration": true, + "composite": true, + "outDir": "./dist", + "rootDir": "./", + "resolveJsonModule": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "lib": ["ES2020", "DOM"], + "types": ["mocha", "chai", "node"] + }, + "include": ["./**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/examples/13-bridge-and-invest-aave/tsconfig.create-config.json b/examples/13-bridge-and-invest-aave/tsconfig.create-config.json new file mode 100644 index 0000000..2500074 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/tsconfig.create-config.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "strict": true, + "target": "es2020", + "rootDir": "src", + "outDir": "dist", + "module": "commonjs", + "esModuleInterop": true, + "sourceMap": true, + "declaration": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "declarationMap": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true + }, + "include": [ + "src/create-config.invest.ts" + ] +} diff --git a/examples/13-bridge-and-invest-aave/tsconfig.json b/examples/13-bridge-and-invest-aave/tsconfig.json new file mode 100644 index 0000000..dd7ad20 --- /dev/null +++ b/examples/13-bridge-and-invest-aave/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "assemblyscript/std/assembly.json", + "include": ["./src/**/*.ts"], + "exclude": ["tests/**/*"], + "references": [{ "path": "./tests" }] +}