diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..880ac59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.DS_Store diff --git a/lending_core/Move.lock b/lending_core/Move.lock index 204e111..f6ce4c9 100644 --- a/lending_core/Move.lock +++ b/lending_core/Move.lock @@ -1,99 +1,281 @@ -# @generated by Move, please check-in and do not edit manually. +# Generated by move; do not edit +# This file should be checked in. [move] -version = 0 -manifest_digest = "96DA4004107CCD5A3C9A633E05388D1D69CF8CC2D9322D0E8E15E2F31E707DE6" -deps_digest = "F9B494B64F0615AED0E98FC12A85B85ECD2BC5185C22D30E7F67786BB52E507C" - -dependencies = [ - { name = "Sui" }, - { name = "math" }, - { name = "oracle" }, - { name = "utils" }, -] - -[[move.package]] -name = "MoveStdlib" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "mainnet", subdir = "crates/sui-framework/packages/move-stdlib" } - -[[move.package]] -name = "Pyth" -source = { git = "https://github.com/naviprotocol/pyth-crosschain.git", rev = "navi-forked", subdir = "target_chains/sui/contracts" } - -dependencies = [ - { name = "Sui" }, - { name = "Wormhole" }, -] - -[[move.package]] -name = "Sui" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "mainnet", subdir = "crates/sui-framework/packages/sui-framework" } - -dependencies = [ - { name = "MoveStdlib" }, -] - -[[move.package]] -name = "SupraOracle" -source = { git = "https://github.com/naviprotocol/dora-interface.git", rev = "main", subdir = "sui/mainnet/supra_holder" } - -dependencies = [ - { name = "Sui" }, - { name = "supra_validator" }, -] - -[[move.package]] -name = "Wormhole" -source = { git = "https://github.com/naviprotocol/wormhole.git", rev = "navi-forked", subdir = "sui/wormhole" } - -dependencies = [ - { name = "Sui" }, -] - -[[move.package]] -name = "math" -source = { local = "../math" } +version = 4 -dependencies = [ - { name = "Sui" }, -] +[pinned.mainnet.MoveStdlib] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "b9149cbf0b2cb9ae5ed830407a9b48c7ae3fd36c" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} -[[move.package]] -name = "oracle" -source = { local = "../oracle" } +[pinned.mainnet.MoveStdlib_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.MoveStdlib_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.MoveStdlib_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.Pyth] +source = { git = "https://github.com/naviprotocol/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "1880b24c6acfaac101747f863c5047fff9adaa0f" } +use_environment = "mainnet" +manifest_digest = "C981BFE5D31B50DB795278F9617725C1C2AEDFE52970A2E02D2B5636175470AB" +deps = { Sui = "Sui_1", Wormhole = "Wormhole" } + +[pinned.mainnet.PythProCompatible] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "mainnet" +manifest_digest = "3D2B5BBF2058F3C9DCA3527CC2486C518124687B60479CA9875E5475652B7BBC" +deps = { Sui = "Sui_2", WormholeSimpleMajority = "WormholeSimpleMajority" } + +[pinned.mainnet.Sui] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "b9149cbf0b2cb9ae5ed830407a9b48c7ae3fd36c" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib" } + +[pinned.mainnet.SuiSystem] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-system", rev = "b9149cbf0b2cb9ae5ed830407a9b48c7ae3fd36c" } +use_environment = "mainnet" +manifest_digest = "CCBB2DE961DACC94644C65D54E808DEF86BC7E9C42A494D5250CC5F99392E069" +deps = { MoveStdlib = "MoveStdlib", Sui = "Sui" } + +[pinned.mainnet.SuiSystem_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-system", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "mainnet" +manifest_digest = "CCBB2DE961DACC94644C65D54E808DEF86BC7E9C42A494D5250CC5F99392E069" +deps = { MoveStdlib = "MoveStdlib_1", Sui = "Sui_1" } + +[pinned.mainnet.Sui_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib_1" } + +[pinned.mainnet.Sui_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib_2" } -dependencies = [ - { name = "Pyth" }, - { name = "Sui" }, - { name = "SupraOracle" }, -] +[pinned.mainnet.Sui_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib_3" } -[[move.package]] -name = "supra_utils" -source = { git = "https://github.com/naviprotocol/dora-interface.git", rev = "main", subdir = "sui/mainnet/supra_utils" } +[pinned.mainnet.SupraOracle] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_holder", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "mainnet" +manifest_digest = "CDD606D609F32BF36A2C06E7DB0E6BBBA82B7EC29C58D217D0AFCED1E87ED550" +deps = { Sui = "Sui_1", supra_validator = "supra_validator" } -dependencies = [ - { name = "Sui" }, -] +[pinned.mainnet.Switchboard] +source = { git = "https://github.com/naviprotocol/navi-smart-contracts.git", subdir = "switchboard_sui/on_demand", rev = "473b0934235d6dc1357fa4309308167c6d175fd1" } +use_environment = "mainnet" +manifest_digest = "BA49968BFF7C4A4D9F013B59535CF8B89D935A7C6D63C121606B1FE844829B72" +deps = { Sui = "Sui_3" } -[[move.package]] -name = "supra_validator" -source = { git = "https://github.com/naviprotocol/dora-interface.git", rev = "main", subdir = "sui/mainnet/supra_validator" } +[pinned.mainnet.Wormhole] +source = { git = "https://github.com/naviprotocol/wormhole.git", subdir = "sui/wormhole", rev = "7749aff1380b0f63743d36856a5934de606483ba" } +use_environment = "mainnet" +manifest_digest = "3876920E3F5449B657525E749B996C31141507452514AF2E259F5441554DCDDF" +deps = { Sui = "Sui_1" } -dependencies = [ - { name = "Sui" }, - { name = "supra_utils" }, -] +[pinned.mainnet.WormholeSimpleMajority] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/vendor/wormhole_simple_majority/wormhole", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "mainnet" +manifest_digest = "0D766A0380B75080707CFA6099AF469A2E502B0D9DC334A9E9983B391C5555D9" +deps = { Sui = "Sui_2" } -[[move.package]] -name = "utils" +[pinned.mainnet.lending_core] +source = { root = true } +use_environment = "mainnet" +manifest_digest = "123EB952E37AC19D27B6FB610CF34259FD2C2F34A468ECAE3E4795F735A44980" +deps = { liquid_staking = "liquid_staking", math = "math", oracle = "oracle", std = "MoveStdlib", sui = "Sui", sui_system = "SuiSystem_1", utils = "utils" } + +[pinned.mainnet.liquid_staking] +source = { git = "https://github.com/naviprotocol/navi-smart-contracts.git", subdir = "volo_liquid_staking", rev = "473b0934235d6dc1357fa4309308167c6d175fd1" } +use_environment = "mainnet" +manifest_digest = "5088FADDD8E68B81993124941C625140D78354C8DCD372C440055B66B7604874" +deps = { std = "MoveStdlib", sui = "Sui", sui_system = "SuiSystem" } + +[pinned.mainnet.math] +source = { local = "../math" } +use_environment = "mainnet" +manifest_digest = "3876920E3F5449B657525E749B996C31141507452514AF2E259F5441554DCDDF" +deps = { Sui = "Sui_1" } + +[pinned.mainnet.oracle] +source = { local = "../oracle" } +use_environment = "mainnet" +manifest_digest = "E04AD78C45C58C917E5B839EC9B849FBD76C699C2EF25F105518CEF9FE6CDA8C" +deps = { SupraOracle = "SupraOracle", pyth = "Pyth", pyth_pro_compatible = "PythProCompatible", std = "MoveStdlib", sui = "Sui", switchboard = "Switchboard" } + +[pinned.mainnet.supra_utils] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_utils", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "mainnet" +manifest_digest = "3876920E3F5449B657525E749B996C31141507452514AF2E259F5441554DCDDF" +deps = { Sui = "Sui_1" } + +[pinned.mainnet.supra_validator] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_validator", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "mainnet" +manifest_digest = "6972115A9F4DCD60D13D7BB34F2D42245F8743B737EA8651F3DF6669BC3D6C93" +deps = { Sui = "Sui_1", supra_utils = "supra_utils" } + +[pinned.mainnet.utils] source = { local = "../utils" } +use_environment = "mainnet" +manifest_digest = "3876920E3F5449B657525E749B996C31141507452514AF2E259F5441554DCDDF" +deps = { Sui = "Sui_1" } + +[pinned.testnet.MoveStdlib] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "d50b78880fdacb1bbde92e6974ed71a7650c1090" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.testnet.MoveStdlib_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.testnet.MoveStdlib_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} -dependencies = [ - { name = "Sui" }, -] +[pinned.testnet.MoveStdlib_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} -[move.toolchain-version] -compiler-version = "1.27.2" -edition = "legacy" -flavor = "sui" +[pinned.testnet.Pyth] +source = { git = "https://github.com/naviprotocol/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "1880b24c6acfaac101747f863c5047fff9adaa0f" } +use_environment = "testnet" +manifest_digest = "485F78616CB77F1A3EA3FC932926DF0B5411D2758EE2BAFA4C4652A4EF06D29B" +deps = { Sui = "Sui_1", Wormhole = "Wormhole" } + +[pinned.testnet.PythProCompatible] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "testnet" +manifest_digest = "AEAC3FAD5DCF925755E55B4498F4CED3B564F87B638049EF0A7C4E9F2EA7E9EC" +deps = { Sui = "Sui_2", WormholeSimpleMajority = "WormholeSimpleMajority" } + +[pinned.testnet.Sui] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "d50b78880fdacb1bbde92e6974ed71a7650c1090" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib" } + +[pinned.testnet.SuiSystem] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-system", rev = "d50b78880fdacb1bbde92e6974ed71a7650c1090" } +use_environment = "testnet" +manifest_digest = "F1655B9F9B8ECE67FDBA648266DD75B48852F63BF2515856E822586882D1CA2A" +deps = { MoveStdlib = "MoveStdlib", Sui = "Sui" } + +[pinned.testnet.SuiSystem_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-system", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "testnet" +manifest_digest = "F1655B9F9B8ECE67FDBA648266DD75B48852F63BF2515856E822586882D1CA2A" +deps = { MoveStdlib = "MoveStdlib_1", Sui = "Sui_1" } + +[pinned.testnet.Sui_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib_1" } + +[pinned.testnet.Sui_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib_2" } + +[pinned.testnet.Sui_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib_3" } + +[pinned.testnet.SupraOracle] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_holder", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "testnet" +manifest_digest = "9C02A35D78AABF65198AAF05ECD1263DA17CF8CDC9057DBD530C7A2EEC5B1DF4" +deps = { Sui = "Sui_1", supra_validator = "supra_validator" } + +[pinned.testnet.Switchboard] +source = { git = "https://github.com/naviprotocol/navi-smart-contracts.git", subdir = "switchboard_sui/on_demand", rev = "473b0934235d6dc1357fa4309308167c6d175fd1" } +use_environment = "testnet" +manifest_digest = "DEE42C89BB3F8EC67C17BC4AE0CEBE14A28F4FA787E857046EAF0FA38D556496" +deps = { Sui = "Sui_3" } + +[pinned.testnet.Wormhole] +source = { git = "https://github.com/naviprotocol/wormhole.git", subdir = "sui/wormhole", rev = "7749aff1380b0f63743d36856a5934de606483ba" } +use_environment = "testnet" +manifest_digest = "C2772B976EC6A56C32071C116C869B6B810C731713A3E79642606E99AE1F55DA" +deps = { Sui = "Sui_1" } + +[pinned.testnet.WormholeSimpleMajority] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/vendor/wormhole_simple_majority/wormhole", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "testnet" +manifest_digest = "6996F1AB8CD448FFBA142C085C488FE8A46B485E61E38A1891EFA52B30D9C12E" +deps = { Sui = "Sui_2" } + +[pinned.testnet.lending_core] +source = { root = true } +use_environment = "testnet" +manifest_digest = "196E198BF2BD8BC01EA0CCE03959B505BF9EAF2CA112826B15513216D2BB852F" +deps = { liquid_staking = "liquid_staking", math = "math", oracle = "oracle", std = "MoveStdlib", sui = "Sui", sui_system = "SuiSystem_1", utils = "utils" } + +[pinned.testnet.liquid_staking] +source = { git = "https://github.com/naviprotocol/navi-smart-contracts.git", subdir = "volo_liquid_staking", rev = "473b0934235d6dc1357fa4309308167c6d175fd1" } +use_environment = "testnet" +manifest_digest = "5E7C288BBC1CF8C7B1A36EC70D1D39D45703A5397C84D65EFD693E7EDFF41766" +deps = { std = "MoveStdlib", sui = "Sui", sui_system = "SuiSystem" } + +[pinned.testnet.math] +source = { local = "../math" } +use_environment = "testnet" +manifest_digest = "C2772B976EC6A56C32071C116C869B6B810C731713A3E79642606E99AE1F55DA" +deps = { Sui = "Sui_1" } + +[pinned.testnet.oracle] +source = { local = "../oracle" } +use_environment = "testnet" +manifest_digest = "B76685B606F186A6557ECD98B4FC6988E9BE0DC3E97F5875DEEDD609D7E9D168" +deps = { SupraOracle = "SupraOracle", pyth = "Pyth", pyth_pro_compatible = "PythProCompatible", std = "MoveStdlib", sui = "Sui", switchboard = "Switchboard" } + +[pinned.testnet.supra_utils] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_utils", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "testnet" +manifest_digest = "C2772B976EC6A56C32071C116C869B6B810C731713A3E79642606E99AE1F55DA" +deps = { Sui = "Sui_1" } + +[pinned.testnet.supra_validator] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_validator", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "testnet" +manifest_digest = "20910F73E6DB180B11201B71A872B16AED4CFEF8AAE1428E33839CB5860A569E" +deps = { Sui = "Sui_1", supra_utils = "supra_utils" } + +[pinned.testnet.utils] +source = { local = "../utils" } +use_environment = "testnet" +manifest_digest = "C2772B976EC6A56C32071C116C869B6B810C731713A3E79642606E99AE1F55DA" +deps = { Sui = "Sui_1" } diff --git a/lending_core/Move.toml b/lending_core/Move.toml index 6f95957..a311b17 100644 --- a/lending_core/Move.toml +++ b/lending_core/Move.toml @@ -1,12 +1,17 @@ [package] name = "lending_core" version = "0.0.1" -published-at = "0x81c408448d0d57b3e371ea94de1d40bf852784d3e225de1e74acab3e8395c18f" -[dependencies.Sui] +[dependencies.sui_system] git = "https://github.com/MystenLabs/sui.git" -subdir = "crates/sui-framework/packages/sui-framework" +subdir = "crates/sui-framework/packages/sui-system" rev = "mainnet" +override = true + +[dependencies.liquid_staking] +git = "https://github.com/naviprotocol/navi-smart-contracts.git" +subdir = "volo_liquid_staking" +rev = "main" [dependencies.math] local = "../math" @@ -16,7 +21,3 @@ local = "../oracle" [dependencies.utils] local = "../utils" - -[addresses] -sui = "0x2" -lending_core = "0xd899cf7d2b5db716bd2cf55599fb0d5ee38a3061e7b6bb6eebf73fa5bc4c81ca" diff --git a/lending_core/Published.toml b/lending_core/Published.toml new file mode 100644 index 0000000..4728f62 --- /dev/null +++ b/lending_core/Published.toml @@ -0,0 +1,9 @@ +# Generated by Move +# This file contains metadata about published versions of this package in different environments +# This file SHOULD be committed to source control + +[published.mainnet] +chain-id = "35834a8a" +published-at = "0x512f28261c1a293f49416d8885b8d5d32bde6dd68a99a0be36fe42b248e6833a" +original-id = "0xd899cf7d2b5db716bd2cf55599fb0d5ee38a3061e7b6bb6eebf73fa5bc4c81ca" +version = 26 diff --git a/lending_core/sources/account.move b/lending_core/sources/account.move index 6c35514..2b474c1 100644 --- a/lending_core/sources/account.move +++ b/lending_core/sources/account.move @@ -1,11 +1,34 @@ module lending_core::account { + use sui::object::{UID}; + use std::ascii::{String}; - #[allow(unused_field)] struct AccountCap has key, store { id: UID, owner: address } + // Display Field For Account Cap + struct AccountField has store { + account_name: String, + account_description: String, + last_update_time: String, + market_balance: String, + } + + // ==== dynamic field keys ==== + struct AccountFieldKey has copy, drop, store {} + native public fun account_owner(cap: &AccountCap): address; -} \ No newline at end of file + + native public fun set_account_name(cap: &mut AccountCap, name: String); + + native public fun set_account_description(cap: &mut AccountCap, description: String); + + native public fun set_last_update_time(cap: &mut AccountCap, last_update_time: String); + + native public fun set_market_balance(cap: &mut AccountCap, balance: String); + + native public fun get_account_info(cap: &AccountCap): (String, String, String, String); + +} diff --git a/lending_core/sources/calculator.move b/lending_core/sources/calculator.move index 9994f09..9d6d641 100644 --- a/lending_core/sources/calculator.move +++ b/lending_core/sources/calculator.move @@ -1,19 +1,33 @@ module lending_core::calculator { + use sui::clock::{Clock}; - use oracle::oracle::{PriceOracle}; - use lending_core::storage::{Storage}; + use oracle::oracle::{Self, PriceOracle}; + use lending_core::storage::{Self, Storage}; native public fun caculate_utilization(storage: &mut Storage, asset: u8): u256; native public fun calculate_borrow_rate(storage: &mut Storage, asset: u8): u256; native public fun calculate_supply_rate(storage: &mut Storage, asset: u8, borrow_rate: u256): u256; - + + /** + * Title: Calculating compound interest + * Input(current_timestamp): 1685029315718 + * Input(last_update_timestamp): 1685029255718 + * Input(rate): 6.3 * 1e27 + */ native public fun calculate_compounded_interest(timestamp_difference: u256, rate: u256): u256; + /** + * Title: Calculating liner interest + * Input(current_timestamp): 1685029315718 + * Input(last_update_timestamp): 1685029255718 + * Input(rate): 6.3 * 1e27 + */ native public fun calculate_linear_interest(timestamp_difference: u256, rate: u256): u256; native public fun calculate_value(clock: &Clock, oracle: &PriceOracle, amount: u256, oracle_id: u8): u256; - + native public fun calculate_amount(clock: &Clock, oracle: &PriceOracle, value: u256, oracle_id: u8): u256; + } diff --git a/lending_core/sources/constants.move b/lending_core/sources/constants.move index 82c6bec..4d3877c 100644 --- a/lending_core/sources/constants.move +++ b/lending_core/sources/constants.move @@ -1,10 +1,24 @@ module lending_core::constants { + public fun seconds_per_year(): u256 {60 * 60 * 24 * 365} + + // incentive v2 & v3 public fun option_type_supply(): u8 {1} + public fun option_type_withdraw(): u8 {2} + public fun option_type_borrow(): u8 {3} + public fun option_type_repay(): u8 {4} + + // storage public fun max_number_of_reserves(): u8 {255} - public fun version(): u64 {6} + + // version + public fun version(): u64 {16} + public fun FlashLoanMultiple(): u64 {10000} -} \ No newline at end of file + + public fun percentage_benchmark(): u64 {10000} + +} diff --git a/lending_core/sources/dynamic_calculator.move b/lending_core/sources/dynamic_calculator.move index 2d6cc2b..07f0fb8 100644 --- a/lending_core/sources/dynamic_calculator.move +++ b/lending_core/sources/dynamic_calculator.move @@ -1,8 +1,10 @@ module lending_core::dynamic_calculator { - use sui::clock::{Clock}; + + use sui::address; + use sui::clock::{Self, Clock}; use oracle::oracle::{PriceOracle}; - use lending_core::pool::{ Pool}; - use lending_core::storage::{Storage}; + use lending_core::pool::{Self, Pool}; + use lending_core::storage::{Self, Storage}; native public fun dynamic_health_factor(clock: &Clock, storage: &mut Storage, oracle: &PriceOracle, pool: &mut Pool, user: address, asset: u8, estimate_supply_value: u64, estimate_borrow_value: u64, is_increase: bool): u256; @@ -24,9 +26,10 @@ module lending_core::dynamic_calculator { native public fun dynamic_calculate_apy(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, estimate_supply_value: u64, estimate_borrow_value: u64, is_increase: bool): (u256, u256); - native public fun dynamic_calculate_borrow_rate( clock: &Clock, storage: &mut Storage, asset: u8, estimate_supply_value: u256, estimate_borrow_value: u256, is_increase: bool): u256; - + native public fun dynamic_calculate_borrow_rate(clock: &Clock, storage: &mut Storage, asset: u8, estimate_supply_value: u256, estimate_borrow_value: u256, is_increase: bool): u256; + native public fun dynamic_calculate_supply_rate(clock: &Clock, storage: &mut Storage, asset: u8, borrow_rate: u256, estimate_supply_value: u256, estimate_borrow_value: u256, is_increase: bool): u256; native public fun dynamic_caculate_utilization(clock: &Clock, storage: &mut Storage, asset: u8, estimate_supply_value: u256, estimate_borrow_value: u256, is_increase: bool): u256; -} \ No newline at end of file + +} diff --git a/lending_core/sources/error.move b/lending_core/sources/error.move index 5f50f60..8ee06ab 100644 --- a/lending_core/sources/error.move +++ b/lending_core/sources/error.move @@ -1,25 +1,77 @@ module lending_core::error { + public fun incorrect_version(): u64 {1400} + public fun not_available_version(): u64 {1401} + public fun paused(): u64 {1500} + public fun not_owner(): u64 {1501} + public fun invalid_price(): u64 {1502} + public fun invalid_amount(): u64 {1503} + public fun invalid_pool(): u64 {1504} + public fun invalid_coin_type(): u64 {1505} + public fun insufficient_balance(): u64 {1506} + + public fun invalid_value(): u64 {1507} + + public fun invalid_function_call(): u64 {1508} + public fun user_is_unhealthy(): u64 {1600} + public fun user_have_no_collateral(): u64 {1601} + public fun user_have_no_loan(): u64 {1602} + public fun ltv_is_not_enough(): u64 {1603} + public fun exceeded_maximum_deposit_cap(): u64 {1604} + public fun exceeded_maximum_borrow_cap(): u64 {1605} + + public fun user_is_healthy(): u64 {1606} + + public fun not_liquidatable(): u64 {1607} + public fun no_more_reserves_allowed(): u64 {1700} + public fun duplicate_reserve(): u64 {1701} + public fun non_single_value(): u64 {1801} + public fun invalid_duration_time(): u64 {1802} + public fun required_parent_account_cap(): u64 {1900} + public fun reserve_not_found(): u64 {2000} + public fun duplicate_config(): u64 {2001} - public fun invalid_user(): u64 {2001} -} \ No newline at end of file + + public fun invalid_user(): u64 {2002} + + public fun pool_not_found(): u64 {2100} + + public fun price_feed_not_found(): u64 {2101} + + public fun rule_not_found(): u64 {2102} + + public fun invalid_funds(): u64 {2103} + + public fun invalid_option(): u64 {2104} + + public fun duplicate_emode(): u64 {3000} + + public fun ineligible_for_emode(): u64 {3001} + + public fun not_in_emode(): u64 {3002} + + public fun emode_is_not_active(): u64 {3003} + + public fun unmatched_market_id(): u64 {3100} + +} diff --git a/lending_core/sources/event.move b/lending_core/sources/event.move new file mode 100644 index 0000000..b1f72dc --- /dev/null +++ b/lending_core/sources/event.move @@ -0,0 +1,373 @@ +/// Event +module lending_core::event { + + use std::ascii::{String}; + + // Flash Loan Event + struct ConfigCreated has copy, drop { + sender: address, + id: address, + market_id: u64, + } + + struct AssetConfigCreated has copy, drop { + sender: address, + config_id: address, + asset_id: address, + market_id: u64, + } + + struct FlashLoan has copy, drop { + sender: address, + asset: address, + amount: u64, + market_id: u64, + } + + struct FlashRepay has copy, drop { + sender: address, + asset: address, + amount: u64, + fee_to_supplier: u64, + fee_to_treasury: u64, + market_id: u64, + } + + // Incentive_v3 Event + // Event + struct RewardFundCreated has copy, drop { + sender: address, + reward_fund_id: address, + coin_type: String, + market_id: u64, + } + + struct RewardFundDeposited has copy, drop { + sender: address, + reward_fund_id: address, + amount: u64, + market_id: u64, + } + + struct RewardFundWithdrawn has copy, drop { + sender: address, + reward_fund_id: address, + amount: u64, + market_id: u64, + } + + struct IncentiveCreated has copy, drop { + sender: address, + incentive_id: address, + market_id: u64, + } + + struct AssetPoolCreated has copy, drop { + sender: address, + asset_id: u8, + asset_coin_type: String, + pool_id: address, + market_id: u64, + } + + struct RuleCreated has copy, drop { + sender: address, + pool: String, + rule_id: address, + option: u8, + reward_coin_type: String, + market_id: u64, + } + + struct BorrowFeeRateUpdated has copy, drop { + sender: address, + rate: u64, + market_id: u64, + } + + struct BorrowFeeWithdrawn has copy, drop { + sender: address, + coin_type: String, + amount: u64, + market_id: u64, + } + + struct RewardStateUpdated has copy, drop { + sender: address, + rule_id: address, + enable: bool, + market_id: u64, + } + + struct MaxRewardRateUpdated has copy, drop { + rule_id: address, + max_total_supply: u64, + duration_ms: u64, + market_id: u64, + } + + struct RewardRateUpdated has copy, drop { + sender: address, + pool: String, + rule_id: address, + rate: u256, + total_supply: u64, + duration_ms: u64, + timestamp: u64, + market_id: u64, + } + + struct RewardClaimed has copy, drop { + user: address, + total_claimed: u64, + coin_type: String, + rule_ids: vector
, + rule_indices: vector, + market_id: u64, + } + + struct AssetBorrowFeeRateUpdated has copy, drop { + sender: address, + asset_id: u8, + user: address, + rate: u64, + market_id: u64, + } + + struct AssetBorrowFeeRateRemoved has copy, drop { + sender: address, + asset_id: u8, + user: address, + market_id: u64, + } + + struct BorrowFeeDeposited has copy, drop { + sender: address, + coin_type: String, + fee: u64, + market_id: u64, + } + + // Lending Event + // Event + struct DepositEvent has copy, drop { + reserve: u8, + sender: address, + amount: u64, + market_id: u64, + } + + struct DepositOnBehalfOfEvent has copy, drop { + reserve: u8, + sender: address, + user: address, + amount: u64, + market_id: u64, + } + + struct WithdrawEvent has copy, drop { + reserve: u8, + sender: address, + to: address, + amount: u64, + market_id: u64, + } + + struct BorrowEvent has copy, drop { + reserve: u8, + sender: address, + amount: u64, + market_id: u64, + } + + struct RepayEvent has copy, drop { + reserve: u8, + sender: address, + amount: u64, + market_id: u64, + } + + struct RepayOnBehalfOfEvent has copy, drop { + reserve: u8, + sender: address, + user: address, + amount: u64, + market_id: u64, + } + + #[allow(unused_field)] + struct LiquidationCallEvent has copy, drop { + reserve: u8, + sender: address, + liquidate_user: address, + liquidate_amount: u64, + market_id: u64, + } + + struct LiquidationEvent has copy, drop { + sender: address, + user: address, + collateral_asset: u8, + collateral_price: u256, + collateral_amount: u64, + treasury: u64, + debt_asset: u8, + debt_price: u256, + debt_amount: u64, + market_id: u64, + } + + // logic Event + struct StateUpdated has copy, drop { + user: address, + asset: u8, + user_supply_balance: u256, + user_borrow_balance: u256, + new_supply_index: u256, + new_borrow_index: u256, + market_id: u64, + } + + // pool_manager Event + struct FundUpdated has copy, drop { + original_sui_amount: u64, + current_sui_amount: u64, + vsui_balance_amount: u64, + // treasury_amount: u64, + target_sui_amount: u64, + manager_id: address, + } + + struct StakingTreasuryWithdrawn has copy, drop { + taken_vsui_balance_amount: u64, + equal_sui_balance_amount: u64, + manager_id: address, + } + + // pool Event + // Event + struct PoolCreate has copy, drop { + creator: address, + coin_type: String, + pool_id: address, + market_id: u64, + } + + struct PoolBalanceRegister has copy, drop { + sender: address, + amount: u64, + new_amount: u64, + pool: String, + market_id: u64, + } + + struct PoolDeposit has copy, drop { + sender: address, + amount: u64, + pool: String, + market_id: u64, + } + + struct PoolWithdraw has copy, drop { + sender: address, + recipient: address, + amount: u64, + pool: String, + market_id: u64, + } + + struct PoolWithdrawReserve has copy, drop { + sender: address, + recipient: address, + amount: u64, + before: u64, + after: u64, + pool: String, + poolId: address, + market_id: u64, + } + + // Event + struct StorageConfiguratorSetting has copy, drop { + sender: address, + configurator: address, + value: bool, + market_id: u64, + } + + struct Paused has copy, drop { + paused: bool, + market_id: u64, + } + + struct WithdrawTreasuryEvent has copy, drop { + sender: address, + recipient: address, + asset: u8, + amount: u256, + poolId: address, + before: u256, + after: u256, + index: u256, + market_id: u64, + } + + struct LiquidatorSet has copy, drop { + liquidator: address, + user: address, + is_liquidatable: bool, + market_id: u64, + } + + struct ProtectedUserSet has copy, drop { + user: address, + is_protected: bool, + market_id: u64, + } + + struct EmodePairCreated has copy, drop { + emode_id: u64, + assetA: u8, + assetB: u8, + market_id: u64, + } + + struct EmodeParamSet has copy, drop { + emode_id: u64, + asset: u8, + value: u256, + param_type: String, + market_id: u64, + } + + struct EmodeActiveSet has copy, drop { + emode_id: u64, + is_active: bool, + market_id: u64, + } + + struct EmodeUserStateChanged has copy, drop { + user: address, + emode_id: u64, + is_entered: bool, + market_id: u64, + } + + struct MarketCreated has copy, drop { market_id: u64 } + + struct BorrowWeightSet has copy, drop { + asset: u8, + weight: u64, + market_id: u64, + } + + struct BorrowWeightRemoved has copy, drop { asset: u8, market_id: u64 } + + struct StorageParamsUpdated has copy, drop { + asset: u8, + param_type: String, + value: u256, + market_id: u64, + } + +} diff --git a/lending_core/sources/flash_loan.move b/lending_core/sources/flash_loan.move index 94fd9e5..9e3d3c8 100644 --- a/lending_core/sources/flash_loan.move +++ b/lending_core/sources/flash_loan.move @@ -1,30 +1,30 @@ module lending_core::flash_loan { - use std::ascii::{String}; + use std::ascii::{String}; use sui::object::{UID}; use sui::table::{Table}; + use lending_core::version::{Self}; + use lending_core::pool::{Self}; + use lending_core::storage::{StorageAdminCap}; - #[allow(unused_field)] struct Config has key, store { id: UID, version: u64, - support_assets: Table, address>, + support_assets: Table, address>, // Table, 0x2::sui::SUI -> address assets: Table, } - #[allow(unused_field)] struct AssetConfig has key, store { id: UID, asset_id: u8, coin_type: String, - pool_id: address, - rate_to_supplier: u64, - rate_to_treasury: u64, + pool_id: address, // lending pool 1000 -> 10 + rate_to_supplier: u64, // x * MultiBy --> 10% == 0.1 * 10000 = 1000, 0.09 -> 0.09 * 80% = supplier + rate_to_treasury: u64, // x * MultiBy --> 10% == 0.1 * 10000 = 1000 max: u64, min: u64, } - #[allow(unused_field)] struct Receipt { user: address, asset: address, @@ -34,8 +34,47 @@ module lending_core::flash_loan { fee_to_treasury: u64, } - // returns user/asset/amount/pool/fee_to_supplier/fee_to_treasury + // === dynamic field keys === + struct MARKET_ID_KEY has copy, drop, store {} + + // Event + struct ConfigCreated has copy, drop { + sender: address, + id: address, + } + + struct AssetConfigCreated has copy, drop { + sender: address, + config_id: address, + asset_id: address, + } + + struct FlashLoan has copy, drop { + sender: address, + asset: address, + amount: u64, + } + + struct FlashRepay has copy, drop { + sender: address, + asset: address, + amount: u64, + fee_to_supplier: u64, + fee_to_treasury: u64, + } + + native public fun version_verification(config: &Config); + + native public fun version_migrate(_: &StorageAdminCap, cfg: &mut Config); + + // only current main market needs to be initialized + // other markets will be initialized when creating reserves + native public fun init_config_for_main_market(_: &StorageAdminCap, config: &mut Config); + native public fun parsed_receipt(receipt: &Receipt): (address, address, u64, address, u64, u64); native public fun get_asset(config: &Config): (address, u8, vector, address, u64, u64, u64, u64); -} \ No newline at end of file + + native public fun get_market_id(config: &Config): u64; + +} diff --git a/lending_core/sources/incentive.move b/lending_core/sources/incentive.move index 6da3dd9..353e298 100644 --- a/lending_core/sources/incentive.move +++ b/lending_core/sources/incentive.move @@ -1,15 +1,20 @@ +#[allow(unused_field)] +// Deprecated: `incentive` is kept for upgrade compatibility only. +// It no longer distributes rewards, and no new reward features will be added here. +// All reward functionality is implemented in `lending_core::incentive_v3`. module lending_core::incentive { - use std::ascii::{String}; + use std::vector; + use std::ascii::{String}; + use sui::coin::{Coin}; use sui::object::{UID}; use sui::table::{Table}; - use sui::clock::{ Clock}; - use sui::balance::{Balance}; + use sui::clock::{Self, Clock}; + use sui::balance::{Self, Balance}; use sui::tx_context::{TxContext}; - use lending_core::storage::{Storage}; - use lending_core::account::{AccountCap}; + use lending_core::storage::{Self, Storage, OwnerCap}; + use lending_core::account::{Self, AccountCap}; - #[allow(unused_field)] struct IncentiveBal has key, store { id: UID, asset: u8, @@ -18,7 +23,6 @@ module lending_core::incentive { balance: Balance } - #[allow(unused_field)] struct PoolInfo has store { id: u8, last_update_time: u64, @@ -34,7 +38,6 @@ module lending_core::incentive { oracle_ids: vector, } - #[allow(unused_field)] struct Incentive has key, store { id: UID, creator: address, @@ -45,6 +48,34 @@ module lending_core::incentive { assets: vector, } + struct PoolOwnerSetting has copy, drop { + sender: address, + owner: u256, + value: bool, + } + + struct PoolAdminSetting has copy, drop { + sender: address, + admin: u256, + value: bool, + } + + struct IncentiveOwnerCap has key, store { + id: UID, + } + + struct IncentiveAdminCap has key, store { + id: UID, + } + + native public fun create_and_transfer_ownership(_owner: address, _ctx: &mut TxContext); + + // Call by creator + native public fun set_owner(incentive: &mut Incentive, owner: u256, val: bool, ctx: &mut TxContext); + + native public fun set_admin(incentive: &mut Incentive, admin: u256, val: bool, ctx: &mut TxContext); + + native public entry fun add_pool(incentive: &mut Incentive, clock: &Clock, asset: u8, start_time: u64, end_time: u64, reward_coin: Coin, amount: u64, oracle_id: u8, ctx: &mut TxContext); native public entry fun claim_reward(incentive: &mut Incentive, bal: &mut IncentiveBal, clock: &Clock, storage: &mut Storage, account: address, ctx: &mut TxContext); @@ -52,9 +83,12 @@ module lending_core::incentive { native public fun claim_reward_with_account_cap(incentive: &mut Incentive, bal: &mut IncentiveBal, clock: &Clock, storage: &mut Storage, account_cap: &AccountCap): Balance; + native public entry fun admin_withdraw_incentive_bal(_: &OwnerCap, storage: &Storage, bal: &mut IncentiveBal, recipient: address, ctx: &mut TxContext); + native public fun get_pool_count(incentive: &Incentive, asset: u8): u64; native public fun get_pool_info(incentive: &Incentive, asset: u8, pool_idx: u64): (u64, u64, u256, u8); native public fun earned(incentive: &Incentive, storage: &mut Storage, clock: &Clock, asset: u8, account: address): (vector, vector, vector); + } diff --git a/lending_core/sources/incentive_v2.move b/lending_core/sources/incentive_v2.move index 3129b13..73dc1ac 100644 --- a/lending_core/sources/incentive_v2.move +++ b/lending_core/sources/incentive_v2.move @@ -1,20 +1,29 @@ +#[lint_allow(self_transfer)] +#[allow(unused_use, lint(public_entry))] +// Deprecated: `incentive_v2` is kept for upgrade compatibility only. +// It no longer distributes rewards, and no new reward features will be added here. +// All reward functionality is implemented in `lending_core::incentive_v3`. module lending_core::incentive_v2 { + + use std::vector::{Self}; use std::type_name::{TypeName}; use sui::coin::{Coin}; - use sui::object::{UID}; + use sui::object::{Self, UID}; use sui::table::{Table}; - use sui::clock::{Clock}; - use sui::balance::{Balance}; + use sui::clock::{Self, Clock}; + use sui::balance::{Self, Balance}; use sui::tx_context::{TxContext}; - use oracle::oracle::{PriceOracle}; - use lending_core::pool::{Pool}; + use lending_core::version::{Self}; use lending_core::account::{AccountCap}; - use lending_core::incentive::{Incentive as IncentiveV1}; - use lending_core::storage::{Storage}; + use lending_core::incentive::{Self as incentive_v1, Incentive as IncentiveV1}; + use lending_core::storage::{Self, Storage, OwnerCap as StorageOwnerCap}; + + struct OwnerCap has key, store { + id: UID, + } - #[allow(unused_field)] struct Incentive has key, store { id: UID, version: u64, @@ -24,18 +33,17 @@ module lending_core::incentive_v2 { funds: Table, } - #[allow(unused_field)] struct IncentivePool has key, store { id: UID, phase: u64, - funds: address, - start_at: u64, - end_at: u64, - closed_at: u64, - total_supply: u64, - option: u8, - asset_id: u8, - factor: u256, + funds: address, // IncentiveFundsPool.id -> pre_check: object::id_to_address(IncentiveFundsPool.id) equals IncentivePool.funds + start_at: u64, // Distribution start time + end_at: u64, // Distribution end time + closed_at: u64, // Distribution closed time, that means you cannot claim after this time. But the administrator can set this value to 0, which means it can always be claimed. + total_supply: u64, // sui::balance::supply_value max is 18446744073709551615u64, see https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/packages/sui-framework/sources/balance.move#L53 + option: u8, // supply, withdraw, borrow, repay or liquidation + asset_id: u8, // the asset id on protocol pool + factor: u256, // the ratio, type in 1e18 last_update_at: u64, distributed: u64, index_reward: u256, @@ -44,7 +52,6 @@ module lending_core::incentive_v2 { total_claimed_of_users: Table, } - #[allow(unused_field)] struct IncentiveFundsPool has key, store { id: UID, oracle_id: u8, @@ -52,13 +59,68 @@ module lending_core::incentive_v2 { coin_type: TypeName, } - #[allow(unused_field)] struct IncentiveFundsPoolInfo has key, store { id: UID, oracle_id: u8, coin_type: TypeName } + // Events + struct CreateFundsPool has copy, drop { + sender: address, + coin_type: TypeName, + oracle_id: u8, + force: bool, + } + + struct IncreasedFunds has copy, drop { + sender: address, + balance_before: u64, + balance_after: u64, + } + + struct WithdrawFunds has copy, drop { + sender: address, + value: u64, + } + + struct CreateIncentive has copy, drop { + sender: address, + incentive_pool_pro: address, + } + + struct CreateIncentivePool has copy, drop { + sender: address, + pool: address, + } + + struct RewardsClaimed has copy, drop { + sender: address, + pool: address, + amount: u64, + } + + native public fun create_and_transfer_owner(_: &StorageOwnerCap, ctx: &mut TxContext); + + native public fun version_verification(incentive: &Incentive); + + native public fun version_migrate(_: &OwnerCap, incentive: &mut Incentive); + + // +++++++++++++++Split: For Funds Pool+++++++++++++++ + native public fun create_funds_pool(_: &OwnerCap, incentive: &mut Incentive, oracle_id: u8, force: bool, ctx: &mut TxContext); + + // TODO: to be entry? + native public fun add_funds(_: &OwnerCap, funds: &mut IncentiveFundsPool, funds_coin: Coin, value: u64, ctx: &mut TxContext); + + native public fun withdraw_funds(_: &OwnerCap, funds: &mut IncentiveFundsPool, value: u64, ctx: &mut TxContext); + + // +++++++++++++++Split: For Incentive Pool+++++++++++++++ + native public fun create_incentive(_: &OwnerCap, ctx: &mut TxContext); + + native public fun create_incentive_pool(_: &OwnerCap, incentive: &mut Incentive, funds: &IncentiveFundsPool, phase: u64, start_at: u64, end_at: u64, closed_at: u64, total_supply: u64, option: u8, asset_id: u8, factor: u256, ctx: &mut TxContext); + + native public fun freeze_incentive_pool(_: &OwnerCap, incentive_v2: &mut Incentive, deadline: u64); + native public entry fun claim_reward(clock: &Clock, incentive: &mut Incentive, funds_pool: &mut IncentiveFundsPool, storage: &mut Storage, asset_id: u8, option: u8, ctx: &mut TxContext); native public fun claim_reward_non_entry(clock: &Clock, incentive: &mut Incentive, funds_pool: &mut IncentiveFundsPool, storage: &mut Storage, asset_id: u8, option: u8, ctx: &TxContext): Balance; @@ -74,6 +136,7 @@ module lending_core::incentive_v2 { native public fun get_pool_from_asset_and_option(incentive: &Incentive, asset_id: u8, option: u8): (vector
, vector
, vector
); native public fun get_active_pools(incentive: &Incentive, asset_id: u8, option: u8, now: u64): vector
; + native public fun get_pool_objects(incentive: &Incentive): vector
; native public fun get_inactive_pool_objects(incentive: &Incentive): vector
; @@ -87,21 +150,7 @@ module lending_core::incentive_v2 { native public fun option_repay(): u8; - native public fun get_pool_info(incentive: &Incentive, obj: address): ( - address, // id - u64, // phase - address, // funds - u64, // start_at - u64, // end_at - u64, // closed_at - u64, // total_supply - u8, // option - u8, // asset_id - u256, // factor - u64, // last_update_at - u64, // distributed - u256 // index_reward - ); + native public fun get_pool_info(incentive: &Incentive, obj: address): (address, u64, address, u64, u64, u64, u64, u8, u8, u256, u64, u64, u256); native public fun get_pool_length(incentive: &Incentive): u64; @@ -113,33 +162,50 @@ module lending_core::incentive_v2 { native public fun get_funds_info(incentive: &Incentive, obj: address): (address, u8, TypeName); + // lending protocol entry function + #[allow(unused_variable)] native public entry fun entry_deposit(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, deposit_coin: Coin, amount: u64, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public fun deposit_with_account_cap(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, deposit_coin: Coin, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, account_cap: &AccountCap); + #[allow(unused_variable)] native public entry fun entry_deposit_on_behalf_of_user(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, deposit_coin: Coin, amount: u64, user: address, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public entry fun entry_withdraw(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public fun withdraw_with_account_cap(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, account_cap: &AccountCap): Balance; + #[allow(unused_variable)] native public fun withdraw(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, ctx: &mut TxContext): Balance; + #[allow(unused_variable)] native public entry fun entry_borrow(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public fun borrow_with_account_cap(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive: &mut Incentive, account_cap: &AccountCap): Balance; + #[allow(unused_variable)] native public fun borrow(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive: &mut Incentive, ctx: &mut TxContext): Balance; + #[allow(unused_variable)] native public entry fun entry_repay(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, amount: u64, incentive: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public fun repay_with_account_cap(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, incentive: &mut Incentive, account_cap: &AccountCap): Balance; + #[allow(unused_variable)] native public fun entry_repay_on_behalf_of_user(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, amount: u64, user: address, incentive: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public fun repay(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, amount: u64, incentive: &mut Incentive, ctx: &mut TxContext): Balance; + #[allow(unused_variable)] native public entry fun entry_liquidation(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, debt_coin: Coin, collateral_asset: u8, collateral_pool: &mut Pool, liquidate_user: address, liquidate_amount: u64, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, ctx: &mut TxContext); + #[allow(unused_variable)] native public fun liquidation(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, debt_balance: Balance, collateral_asset: u8, collateral_pool: &mut Pool, liquidate_user: address, incentive_v1: &mut IncentiveV1, incentive_v2: &mut Incentive, ctx: &mut TxContext): (Balance, Balance); -} \ No newline at end of file + +} diff --git a/lending_core/sources/incentive_v3.move b/lending_core/sources/incentive_v3.move index 29b2804..b6820f4 100644 --- a/lending_core/sources/incentive_v3.move +++ b/lending_core/sources/incentive_v3.move @@ -1,23 +1,29 @@ -#[allow(unused_field)] +/// The `incentive_v3` module manages the incentive structures for the lending protocol. +/// It includes functionality for creating and managing incentives, pools, and rules, +/// as well as handling reward distribution and borrow fee management. +#[allow(unused_variable, lint(public_entry))] module lending_core::incentive_v3 { + use std::vector::{Self}; use std::ascii::{String}; + use std::type_name::{TypeName}; use sui::bag::{Bag}; use sui::object::{UID}; use sui::coin::{Coin}; use sui::table::{Table}; - use sui::clock::{Clock}; - use sui::balance::{Balance}; + use sui::clock::{Self, Clock}; + use sui::balance::{Self, Balance}; use sui::vec_map::{VecMap}; use sui::tx_context::{TxContext}; - use lending_core::pool::{Pool}; - use lending_core::storage::{Storage}; + use lending_core::version::{Self}; + use lending_core::storage::{Self, Storage}; use lending_core::account::{AccountCap}; - use lending_core::incentive_v2::{Incentive as IncentiveV2}; + use lending_core::incentive_v2::{Self, Incentive as IncentiveV2}; use oracle::oracle::{PriceOracle}; + use lending_core::storage::StorageAdminCap; + use sui_system::sui_system::{SuiSystemState}; - // Main structs struct Incentive has key, store { id: UID, version: u64, @@ -62,61 +68,246 @@ module lending_core::incentive_v3 { rule_ids: vector
, } - // Reward claiming + // Event + struct RewardFundCreated has copy, drop { + sender: address, + reward_fund_id: address, + coin_type: String, + } + + struct RewardFundDeposited has copy, drop { + sender: address, + reward_fund_id: address, + amount: u64, + } + + struct RewardFundWithdrawn has copy, drop { + sender: address, + reward_fund_id: address, + amount: u64, + } + + struct IncentiveCreated has copy, drop { + sender: address, + incentive_id: address, + } + + struct AssetPoolCreated has copy, drop { + sender: address, + asset_id: u8, + asset_coin_type: String, + pool_id: address, + } + + struct RuleCreated has copy, drop { + sender: address, + pool: String, + rule_id: address, + option: u8, + reward_coin_type: String, + } + + struct BorrowFeeRateUpdated has copy, drop { + sender: address, + rate: u64, + } + + struct BorrowFeeWithdrawn has copy, drop { + sender: address, + coin_type: String, + amount: u64, + } + + struct RewardStateUpdated has copy, drop { + sender: address, + rule_id: address, + enable: bool, + } + + struct MaxRewardRateUpdated has copy, drop { + rule_id: address, + max_total_supply: u64, + duration_ms: u64, + } + + struct RewardRateUpdated has copy, drop { + sender: address, + pool: String, + rule_id: address, + rate: u256, + total_supply: u64, + duration_ms: u64, + timestamp: u64, + } + + struct RewardClaimed has copy, drop { + user: address, + total_claimed: u64, + coin_type: String, + rule_ids: vector
, + rule_indices: vector, + } + + struct AssetBorrowFeeRateUpdated has copy, drop { + sender: address, + asset_id: u8, + user: address, + rate: u64, + } + + struct AssetBorrowFeeRateRemoved has copy, drop { + sender: address, + asset_id: u8, + user: address, + } + + struct BorrowFeeDeposited has copy, drop { + sender: address, + coin_type: String, + fee: u64 + } + + // === dynamic field keys === + struct ASSET_BORROW_FEES_KEY has copy, drop, store {} + + struct USER_BORROW_FEES_KEY has copy, drop, store {} + + struct MARKET_ID_KEY has copy, drop, store {} + + // Functions + native public fun version(incentive: &Incentive): u64; + + native public fun version_verification(incentive: &Incentive); + + native public fun init_for_main_market(_: &StorageAdminCap, incentive: &mut Incentive); + + native public fun init_fund_for_market(_: &StorageAdminCap, reward_fund: &mut RewardFund); + + native public fun contains_rule(pool: &AssetPool, option: u8, reward_coin_type: String): bool; + + // returns: user_total_supply, user_total_borrow, total_supply, total_borrow + native public fun get_effective_balance(storage: &mut Storage, asset: u8, user: address): (u256, u256, u256, u256); + + /** update the reward state by asset + * @param clock: the clock + * @param incentive: the incentive + * @param storage: the storage + * @param user: the user address + */ + native public fun update_reward_state_by_asset(clock: &Clock, incentive: &mut Incentive, storage: &mut Storage, user: address); + + // Public Get Functions + /// Returns the pools of the incentive.Keys are the coin type of the pool. + native public fun pools(incentive: &Incentive): &VecMap; + + // Pool + native public fun get_pool_info(pool: &AssetPool): (address, u8, String, &VecMap); + + // Rule Info + // id: UID, + // option: u8, + // enable: bool, + // reward_coin_type: String, + // rate: u256, + // last_update_at: u64, + // global_index: u256, + // user_index: Table, + // user_total_rewards: Table, + // user_rewards_claimed: Table, + native public fun get_rule_info(rule: &Rule): (address, u8, bool, String, u256, u64, u256, &Table, &Table, &Table); + + native public fun get_user_index_by_rule(rule: &Rule, user: address): u256; + + native public fun get_user_total_rewards_by_rule(rule: &Rule, user: address): u256; + + native public fun get_user_rewards_claimed_by_rule(rule: &Rule, user: address): u256; + + native public fun get_balance_value_by_reward_fund(reward_fund: &RewardFund): u64; + + native public fun get_user_claimable_rewards(clock: &Clock, storage: &mut Storage, incentive: &Incentive, user: address): vector; + + /// parse the claimable rewards to return the asset coin types, reward coin types, user total rewards, user claimed rewards, and rule ids + native public fun parse_claimable_rewards(claimable_rewards: vector): (vector, vector, vector, vector, vector>); + + // Public functions native public fun claim_reward(clock: &Clock, incentive: &mut Incentive, storage: &mut Storage, reward_fund: &mut RewardFund, coin_types: vector, rule_ids: vector
, ctx: &mut TxContext): Balance; + #[allow(lint(self_transfer))] native public entry fun claim_reward_entry(clock: &Clock, incentive: &mut Incentive, storage: &mut Storage, reward_fund: &mut RewardFund, coin_types: vector, rule_ids: vector
, ctx: &mut TxContext); - + native public fun claim_reward_with_account_cap(clock: &Clock, incentive: &mut Incentive, storage: &mut Storage, reward_fund: &mut RewardFund, coin_types: vector, rule_ids: vector
, account_cap: &AccountCap): Balance; - // Core lending operations with incentive native public entry fun entry_deposit(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, deposit_coin: Coin, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); - + native public fun deposit_with_account_cap(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, deposit_coin: Coin, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, account_cap: &AccountCap); - + native public entry fun entry_deposit_on_behalf_of_user(clock: &Clock, storage: &mut Storage, pool: &mut Pool, asset: u8, deposit_coin: Coin, amount: u64, user: address, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public entry fun entry_withdraw(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); - + + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public entry fun entry_withdraw_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public fun withdraw_with_account_cap(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, account_cap: &AccountCap): Balance; - + + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun withdraw_with_account_cap_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, account_cap: &AccountCap, system_state: &mut SuiSystemState, ctx: &mut TxContext): Balance; + + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public fun withdraw(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext): Balance; + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun withdraw_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, system_state: &mut SuiSystemState, ctx: &mut TxContext): Balance; + + native public fun get_borrow_fee_v2(incentive: &Incentive, user: address, asset_id: u8, amount: u64): u64; + + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public entry fun entry_borrow(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); - + + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public entry fun entry_borrow_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public fun borrow_with_account_cap(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, account_cap: &AccountCap): Balance; - + + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun borrow_with_account_cap_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, account_cap: &AccountCap, system_state: &mut SuiSystemState, ctx: &mut TxContext): Balance; + + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public fun borrow(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext): Balance; + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun borrow_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, system_state: &mut SuiSystemState, ctx: &mut TxContext): Balance; + native public entry fun entry_repay(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); - + native public fun repay_with_account_cap(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, account_cap: &AccountCap): Balance; - + + #[allow(lint(self_transfer))] native public fun entry_repay_on_behalf_of_user(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, amount: u64, user: address, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); - + native public fun repay(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, pool: &mut Pool, asset: u8, repay_coin: Coin, amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext): Balance; + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public entry fun entry_liquidation(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, debt_coin: Coin, collateral_asset: u8, collateral_pool: &mut Pool, liquidate_user: address, liquidate_amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext); - + + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public entry fun entry_liquidation_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, debt_coin: Coin, collateral_asset: u8, collateral_pool: &mut Pool, liquidate_user: address, liquidate_amount: u64, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + // V1: Only supports non-SUI assets. May be deprecated in the future, use v2 instead. native public fun liquidation(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, debt_balance: Balance, collateral_asset: u8, collateral_pool: &mut Pool, liquidate_user: address, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, ctx: &mut TxContext): (Balance, Balance); - // Getter functions - native public fun pools(incentive: &Incentive): &VecMap; - - native public fun get_pool_info(pool: &AssetPool): (address, u8, String, &VecMap); - - native public fun get_rule_info(rule: &Rule): (address, u8, bool, String, u256, u64, u256, &Table, &Table, &Table); - - native public fun get_user_index_by_rule(rule: &Rule, user: address): u256; - - native public fun get_user_total_rewards_by_rule(rule: &Rule, user: address): u256; - - native public fun get_user_rewards_claimed_by_rule(rule: &Rule, user: address): u256; - - native public fun get_balance_value_by_reward_fund(reward_fund: &RewardFund): u64; - - native public fun get_user_claimable_rewards(clock: &Clock, storage: &mut Storage, incentive: &Incentive, user: address): vector; + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun liquidation_v2(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, debt_balance: Balance, collateral_asset: u8, collateral_pool: &mut Pool, liquidate_user: address, incentive_v2: &mut IncentiveV2, incentive_v3: &mut Incentive, system_state: &mut SuiSystemState, ctx: &mut TxContext): (Balance, Balance); - // parse the claimable rewards to return the asset coin types, reward coin types, user total rewards, user claimed rewards, and rule ids - native public fun parse_claimable_rewards(claimable_rewards: vector): (vector, vector, vector, vector, vector>); -} \ No newline at end of file + native public fun get_market_id(incentive_v3: &Incentive): u64; + + native public fun get_fund_market_id(reward_fund: &RewardFund): u64; + + native public fun verify_market_storage_incentive(storage: &Storage, incentive: &Incentive); + + native public fun verify_market_incentive_funds(incentive: &Incentive, funds_pool: &RewardFund); + +} diff --git a/lending_core/sources/lending.move b/lending_core/sources/lending.move index 5271319..4f8d374 100644 --- a/lending_core/sources/lending.move +++ b/lending_core/sources/lending.move @@ -1,40 +1,123 @@ +#[allow(unused_mut_parameter, unused_function)] module lending_core::lending { + use sui::balance::{Balance}; use sui::clock::{Clock}; use sui::coin::{Coin}; use sui::tx_context::{TxContext}; use oracle::oracle::{PriceOracle}; - - use lending_core::pool::{Pool}; - use lending_core::storage::{Storage}; + use lending_core::pool::{Self, Pool}; + use lending_core::storage::{Self, Storage}; use lending_core::incentive::{Incentive}; use lending_core::account::{AccountCap}; use lending_core::flash_loan::{Config as FlashLoanConfig, Receipt as FlashLoanReceipt}; + use sui_system::sui_system::{SuiSystemState}; + + // Event + struct DepositEvent has copy, drop { + reserve: u8, + sender: address, + amount: u64, + } + + struct DepositOnBehalfOfEvent has copy, drop { + reserve: u8, + sender: address, + user: address, + amount: u64, + } + + struct WithdrawEvent has copy, drop { + reserve: u8, + sender: address, + to: address, + amount: u64, + } + + struct BorrowEvent has copy, drop { + reserve: u8, + sender: address, + amount: u64, + } + + struct RepayEvent has copy, drop { + reserve: u8, + sender: address, + amount: u64, + } + + struct RepayOnBehalfOfEvent has copy, drop { + reserve: u8, + sender: address, + user: address, + amount: u64, + } + + #[allow(unused_field)] + struct LiquidationCallEvent has copy, drop { + reserve: u8, + sender: address, + liquidate_user: address, + liquidate_amount: u64, + } + + struct LiquidationEvent has copy, drop { + sender: address, + user: address, + collateral_asset: u8, + collateral_price: u256, + collateral_amount: u64, + treasury: u64, + debt_asset: u8, + debt_price: u256, + debt_amount: u64, + } - // Deprecated native public entry fun deposit(_clock: &Clock, _storage: &mut Storage, _pool: &mut Pool, _asset: u8, _deposit_coin: Coin, _amount: u64, _incentive: &mut Incentive, _ctx: &mut TxContext); - // Deprecated native public entry fun withdraw(_clock: &Clock, _oracle: &PriceOracle, _storage: &mut Storage, _pool: &mut Pool, _asset: u8, _amount: u64, _to: address, _incentive: &mut Incentive, _ctx: &mut TxContext); - // Deprecated native public entry fun borrow(_clock: &Clock, _oracle: &PriceOracle, _storage: &mut Storage, _pool: &mut Pool, _asset: u8, _amount: u64, _ctx: &mut TxContext); - // Deprecated native public entry fun repay(_clock: &Clock, _oracle: &PriceOracle, _storage: &mut Storage, _pool: &mut Pool, _asset: u8, _repay_coin: Coin, _amount: u64, _ctx: &mut TxContext); - // Deprecated - native public entry fun liquidation_call(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, debt_asset: u8, debt_pool: &mut Pool, collateral_asset: u8, collateral_pool: &mut Pool, debt_coin: Coin, liquidate_user: address, liquidate_amount: u64, incentive: &mut Incentive, ctx: &mut TxContext); + native public entry fun liquidation_call(_clock: &Clock, _oracle: &PriceOracle, _storage: &mut Storage, _debt_asset: u8, _debt_pool: &mut Pool, _collateral_asset: u8, _collateral_pool: &mut Pool, _debt_coin: Coin, _liquidate_user: address, _liquidate_amount: u64, _incentive: &mut Incentive, _ctx: &mut TxContext); + // Account Cap native public fun create_account(ctx: &mut TxContext): AccountCap; - native public fun delete_account(cap: AccountCap); + native public fun delete_account(_cap: AccountCap); native public fun flash_loan_with_ctx(config: &FlashLoanConfig, pool: &mut Pool, amount: u64, ctx: &mut TxContext): (Balance, FlashLoanReceipt); + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun flash_loan_with_ctx_v2(config: &FlashLoanConfig, pool: &mut Pool, amount: u64, system_state: &mut SuiSystemState, ctx: &mut TxContext): (Balance, FlashLoanReceipt); + native public fun flash_loan_with_account_cap(config: &FlashLoanConfig, pool: &mut Pool, amount: u64, account_cap: &AccountCap): (Balance, FlashLoanReceipt); + // V2: Supports all assets. Adds sui_system and ctx parameters for SUI pools with staking/unstaking. + native public fun flash_loan_with_account_cap_v2(config: &FlashLoanConfig, pool: &mut Pool, amount: u64, account_cap: &AccountCap, system_state: &mut SuiSystemState, ctx: &mut TxContext): (Balance, FlashLoanReceipt); + native public fun flash_repay_with_ctx(clock: &Clock, storage: &mut Storage, pool: &mut Pool, receipt: FlashLoanReceipt, repay_balance: Balance, ctx: &mut TxContext): Balance; native public fun flash_repay_with_account_cap(clock: &Clock, storage: &mut Storage, pool: &mut Pool, receipt: FlashLoanReceipt, repay_balance: Balance, account_cap: &AccountCap): Balance; -} \ No newline at end of file + + native public fun verify_market_storage_pool(storage: &Storage, pool: &Pool); + + native public fun verify_market_flash_loan_config_pool(config: &FlashLoanConfig, pool: &Pool); + + // ------------------ Emode related functions ------------------ + native public fun enter_emode(storage: &mut Storage, emode_id: u64, ctx: &mut TxContext); + + native public fun enter_emode_with_account_cap(storage: &mut Storage, emode_id: u64, account_cap: &AccountCap); + + native public fun exit_emode(storage: &mut Storage, ctx: &mut TxContext); + + native public fun exit_emode_with_account_cap(storage: &mut Storage, account_cap: &AccountCap); + + // ------------------ State related functions ------------------ + native public fun update_state_of_user(clock: &Clock, storage: &mut Storage, user: address); + + native public fun update_state_of_all(clock: &Clock, storage: &mut Storage); + +} diff --git a/lending_core/sources/logic.move b/lending_core/sources/logic.move index 7072f3b..9761bd9 100644 --- a/lending_core/sources/logic.move +++ b/lending_core/sources/logic.move @@ -1,34 +1,91 @@ module lending_core::logic { - use sui::clock::{Clock}; + use std::vector; + use sui::address; + use sui::clock::{Self, Clock}; use oracle::oracle::{PriceOracle}; - use lending_core::storage::{Storage}; + use lending_core::storage::{Self, Storage}; + struct StateUpdated has copy, drop { + user: address, + asset: u8, + user_supply_balance: u256, + user_borrow_balance: u256, + new_supply_index: u256, + new_borrow_index: u256, + } + + /** + * Title: check the user's health status, is the health factors greater than 1. + * Returns: true/false. + */ native public fun is_health(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, user: address): bool; native public fun user_health_factor_batch(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, users: vector
): vector; + /** + * Title: get the user's health factors. + * Returns: RAY. + */ native public fun user_health_factor(clock: &Clock, storage: &mut Storage, oracle: &PriceOracle, user: address): u256; native public fun dynamic_liquidation_threshold(clock: &Clock, storage: &mut Storage, oracle: &PriceOracle, user: address): u256; + /** + * Title: get the number of collateral (based on the liquidation threshold and LTV) that the user has in all assets. + * Returns: USD amount. + */ native public fun user_health_collateral_value(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, user: address): u256; + /** + * Title: get the number of borrowings the user has in all asset. + * Returns: USD amount. + */ native public fun user_health_loan_value(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, user: address): u256; + // user_health_loan_value scaled by borrow weight + native public fun weighted_user_health_loan_value(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, user: address): u256; + + /** + * Title: get the number of borrowings the user has in given asset. + * Returns: USD amount. + */ native public fun user_loan_value(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, asset: u8, user: address): u256; + /** + * Title: get the number of collaterals the user has in given asset. + * Returns: USD amount. + */ native public fun user_collateral_value(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, asset: u8, user: address): u256; + /** + * Title: get the number of collaterals the user has in given asset, include interest. + * Returns: token amount. + */ native public fun user_collateral_balance(storage: &mut Storage, asset: u8, user: address): u256; + /** + * Title: get the number of borrowings the user has in given asset, include interest. + * Returns: token amount. + */ native public fun user_loan_balance(storage: &mut Storage, asset: u8, user: address): u256; + /** + * Title: check if the user's collateral list contains assets. + * Returns: true/false. + */ native public fun is_collateral(storage: &mut Storage, asset: u8, user: address): bool; + /** + * Title: check if the user's loan list contains assets. + * Returns: true/false. + */ native public fun is_loan(storage: &mut Storage, asset: u8, user: address): bool; - + native public fun calculate_avg_ltv(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, user: address): u256; + // this is logically the same as dynamic_liquidation_threshold + // was used in old version, now is a pure getter function native public fun calculate_avg_threshold(clock: &Clock, oracle: &PriceOracle, storage: &mut Storage, user: address): u256; -} \ No newline at end of file + +} diff --git a/lending_core/sources/manage.move b/lending_core/sources/manage.move index 333a51d..389700c 100644 --- a/lending_core/sources/manage.move +++ b/lending_core/sources/manage.move @@ -1 +1,103 @@ -module lending_core::manage {} \ No newline at end of file +module lending_core::manage { + + use sui::object::{UID}; + use sui::clock::{Clock}; + use sui::coin::{Coin}; + use sui::tx_context::{TxContext}; + use lending_core::pool::{Self, Pool}; + use lending_core::storage::{Self, Storage}; + use lending_core::storage::{StorageAdminCap, OwnerCap as StorageOwnerCap}; + use lending_core::flash_loan::{Config as FlashLoanConfig}; + use lending_core::incentive_v2::{OwnerCap as IncentiveOwnerCap}; + use lending_core::incentive_v3::{Incentive as IncentiveV3, RewardFund}; + use lending_core::storage::EmodeAsset; + + struct BorrowFeeCap has key, store { + id: UID, + } + + #[allow(unused_variable)] + native public fun create_flash_loan_config(_: &StorageAdminCap, ctx: &mut TxContext); + + native public fun create_flash_loan_config_with_storage(_: &StorageAdminCap, storage: &Storage, ctx: &mut TxContext); + + native public fun create_flash_loan_asset(_: &StorageAdminCap, config: &mut FlashLoanConfig, storage: &Storage, pool: &Pool, asset_id: u8, rate_to_supplier: u64, rate_to_treasury: u64, maximum: u64, minimum: u64, ctx: &mut TxContext); + + native public fun set_flash_loan_asset_rate_to_supplier(_: &StorageAdminCap, config: &mut FlashLoanConfig, _value: u64); + + native public fun set_flash_loan_asset_rate_to_treasury(_: &StorageAdminCap, config: &mut FlashLoanConfig, _value: u64); + + native public fun set_flash_loan_asset_min(_: &StorageAdminCap, config: &mut FlashLoanConfig, _value: u64); + + native public fun set_flash_loan_asset_max(_: &StorageAdminCap, config: &mut FlashLoanConfig, _value: u64); + + // Incentive V3 + native public fun withdraw_borrow_fee(_: &StorageAdminCap, incentive: &mut IncentiveV3, amount: u64, recipient: address, ctx: &mut TxContext); + + native public fun incentive_v3_version_migrate(_: &StorageAdminCap, incentive: &mut IncentiveV3); + + native public fun create_incentive_v3_reward_fund(_: &IncentiveOwnerCap, ctx: &mut TxContext); + + native public fun create_incentive_v3_reward_fund_with_storage(_: &IncentiveOwnerCap, storage: &Storage, ctx: &mut TxContext); + + #[allow(lint(self_transfer))] + native public fun deposit_incentive_v3_reward_fund(_: &IncentiveOwnerCap, reward_fund: &mut RewardFund, deposit_coin: Coin, amount: u64, ctx: &mut TxContext); + + native public fun withdraw_incentive_v3_reward_fund(_: &StorageAdminCap, reward_fund: &mut RewardFund, amount: u64, recipient: address, ctx: &mut TxContext); + + native public fun create_incentive_v3(_: &IncentiveOwnerCap, ctx: &mut TxContext); + + native public fun create_incentive_v3_with_storage(_: &IncentiveOwnerCap, storage: &Storage, ctx: &mut TxContext); + + native public fun create_incentive_v3_pool(_: &IncentiveOwnerCap, incentive: &mut IncentiveV3, storage: &Storage, asset_id: u8, ctx: &mut TxContext); + + native public fun create_incentive_v3_rule(_: &IncentiveOwnerCap, clock: &Clock, incentive: &mut IncentiveV3, option: u8, ctx: &mut TxContext); + + native public fun enable_incentive_v3_by_rule_id(_: &IncentiveOwnerCap, incentive: &mut IncentiveV3, rule_id: address, ctx: &mut TxContext); + + native public fun disable_incentive_v3_by_rule_id(_: &IncentiveOwnerCap, incentive: &mut IncentiveV3, rule_id: address, ctx: &mut TxContext); + + native public fun set_incentive_v3_reward_rate_by_rule_id(_: &IncentiveOwnerCap, clock: &Clock, incentive: &mut IncentiveV3, storage: &mut Storage, rule_id: address, total_supply: u64, duration_ms: u64, ctx: &mut TxContext); + + native public fun set_incentive_v3_max_reward_rate_by_rule_id(_: &IncentiveOwnerCap, incentive: &mut IncentiveV3, rule_id: address, max_total_supply: u64, duration_ms: u64); + + native public fun set_incentive_v3_borrow_fee_rate(_: &StorageAdminCap, incentive: &mut IncentiveV3, rate: u64, ctx: &mut TxContext); + + // init + native public fun init_fields_batch(_: &StorageOwnerCap, storage: &mut Storage, incentive: &mut IncentiveV3, ctx: &mut TxContext); + + native public fun mint_borrow_fee_cap(_: &StorageAdminCap, recipient: address, ctx: &mut TxContext); + + native public fun set_borrow_fee_rate(_: &BorrowFeeCap, incentive: &mut IncentiveV3, rate: u64, ctx: &mut TxContext); + + native public fun set_asset_borrow_fee_rate(_: &BorrowFeeCap, incentive: &mut IncentiveV3, asset_id: u8, rate: u64, ctx: &mut TxContext); + + native public fun set_user_borrow_fee_rate(_: &BorrowFeeCap, incentive: &mut IncentiveV3, user: address, asset_id: u8, rate: u64, ctx: &mut TxContext); + + native public fun remove_incentive_v3_asset_borrow_fee_rate(_: &BorrowFeeCap, incentive: &mut IncentiveV3, asset_id: u8, ctx: &mut TxContext); + + native public fun remove_incentive_v3_user_borrow_fee_rate(_: &BorrowFeeCap, incentive: &mut IncentiveV3, user: address, asset_id: u8, ctx: &TxContext); + + native public fun set_designated_liquidators(_: &StorageOwnerCap, storage: &mut Storage, liquidator: address, user: address, is_designated: bool, ctx: &mut TxContext); + + native public fun set_protected_liquidation_users(_: &StorageOwnerCap, storage: &mut Storage, user: address, is_protected: bool); + + native public fun create_emode_asset(_: &StorageAdminCap, asset: u8, is_collateral: bool, is_debt: bool, ltv: u256, lt: u256, liquidation_bonus: u256): EmodeAsset; + + native public fun create_emode_pair(_: &StorageAdminCap, storage: &mut Storage, assetA: EmodeAsset, assetB: EmodeAsset); + + native public fun set_emode_config_active(_: &StorageAdminCap, storage: &mut Storage, emode_id: u64, is_active: bool); + + native public fun set_emode_asset_lt(_: &StorageAdminCap, storage: &mut Storage, emode_id: u64, asset: u8, lt: u256); + + native public fun set_emode_asset_ltv(_: &StorageAdminCap, storage: &mut Storage, emode_id: u64, asset: u8, ltv: u256); + + native public fun set_emode_asset_liquidation_bonus(_: &StorageAdminCap, storage: &mut Storage, emode_id: u64, asset: u8, liquidation_bonus: u256); + + native public fun create_new_market(_: &StorageAdminCap, main_storage: &mut Storage, ctx: &mut TxContext); + + native public fun set_borrow_weight(_: &StorageAdminCap, storage: &mut Storage, asset: u8, weight: u64); + + native public fun remove_borrow_weight(_: &StorageAdminCap, storage: &mut Storage, asset: u8); + +} diff --git a/lending_core/sources/pool.move b/lending_core/sources/pool.move index adfb48f..a8098a1 100644 --- a/lending_core/sources/pool.move +++ b/lending_core/sources/pool.move @@ -1,22 +1,111 @@ #[allow(unused_field, unused_mut_parameter)] module lending_core::pool { + + use std::ascii::{String}; + use sui::coin::{Coin}; use sui::object::{UID}; - use sui::balance::{Balance}; + use sui::balance::{Self, Balance}; + use sui::tx_context::{TxContext}; + use sui::vec_map::{VecMap}; + use sui_system::sui_system::{SuiSystemState}; + use sui::sui::{SUI}; + use liquid_staking::stake_pool::{StakePool, OperatorCap}; + use liquid_staking::cert::{Metadata, CERT}; + // The treasury pool, which is used to hold all the funds struct Pool has key, store { id: UID, - balance: Balance, + balance: Balance, // BTC. ETH treasury_balance: Balance, decimal: u8, } + struct PoolAdminCap has key, store { + id: UID, + creator: address, + } + + // Event + struct PoolCreate has copy, drop { + creator: address, + } + + struct PoolBalanceRegister has copy, drop { + sender: address, + amount: u64, + new_amount: u64, + pool: String, + } + + struct PoolDeposit has copy, drop { + sender: address, + amount: u64, + pool: String, + } + + struct PoolWithdraw has copy, drop { + sender: address, + recipient: address, + amount: u64, + pool: String, + } + + struct PoolWithdrawReserve has copy, drop { + sender: address, + recipient: address, + amount: u64, + before: u64, + after: u64, + pool: String, + poolId: address, + } + + // === dynamic field keys === + struct PoolManagerKey has copy, drop, store {} + + struct MarketIdKey has copy, drop, store {} + + // only current main market needs to be initialized + // other markets will be initialized when creating reserves + native public fun init_pool_for_main_market(_: &PoolAdminCap, pool: &mut Pool); + + native public fun withdraw_treasury(_cap: &mut PoolAdminCap, pool: &mut Pool, amount: u64, recipient: address, ctx: &mut TxContext); + + /// Get coin decimal native public fun get_coin_decimal(pool: &Pool): u8; + /// Convert amount from current decimal to target decimal native public fun convert_amount(amount: u64, cur_decimal: u8, target_decimal: u8): u64; + /// Normal coin amount in dola protocol native public fun normal_amount(pool: &Pool, amount: u64): u64; + /// Unnormal coin amount in dola protocol native public fun unnormal_amount(pool: &Pool, amount: u64): u64; native public fun uid(pool: &Pool): &UID; -} \ No newline at end of file + + // ------Pool Manager------ + native public fun init_sui_pool_manager(_: &PoolAdminCap, pool: &mut Pool, stake_pool: StakePool, metadata: Metadata, target_sui_amount: u64, ctx: &mut TxContext); + + native public fun enable_manage(_: &PoolAdminCap, pool: &mut Pool); + + native public fun disable_manage(_: &PoolAdminCap, pool: &mut Pool); + + native public fun refresh_stake(pool: &mut Pool, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + native public fun withdraw_vsui_from_treasury(_: &PoolAdminCap, pool: &mut Pool, recipient: address, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + native public fun set_target_sui_amount(_: &PoolAdminCap, pool: &mut Pool, target_sui_amount: u64, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + native public fun unstake_vsui(pool: &mut Pool, system_state: &mut SuiSystemState, vsui_coin: Coin, ctx: &mut TxContext): Coin; + + native public fun set_validator_weights_vsui(pool: &mut Pool, system_state: &mut SuiSystemState, vsui_operator_cap: &OperatorCap, validator_weights: VecMap, ctx: &mut TxContext); + + native public fun direct_deposit_sui(_: &PoolAdminCap, pool: &mut Pool, sui_coin: Coin, ctx: &mut TxContext); + + native public fun get_treasury_sui_amount(pool: &Pool): u64; + + native public fun get_market_id(pool: &Pool): u64; + +} diff --git a/lending_core/sources/pool_manager.move b/lending_core/sources/pool_manager.move new file mode 100644 index 0000000..3ffffb3 --- /dev/null +++ b/lending_core/sources/pool_manager.move @@ -0,0 +1,43 @@ +#[allow(unused_field, unused_mut_parameter)] +module lending_core::pool_manager { + + use sui::bag::{Bag}; + use sui::object::{UID}; + use sui::balance::{Balance}; + use std::u64; + use liquid_staking::stake_pool::{StakePool}; + use liquid_staking::cert::{Metadata, CERT}; + + // The treasury pool, which is used to hold all the funds + struct SuiPoolManager has key, store { + id: UID, + // the theoretical sui amount of the pool + // original_sui_amount = sum(sui_deposit) - sum(sui_withdraw) + original_sui_amount: u64, + vsui_balance: Balance, + temp_sui_balance: Bag, + enabled_manage: bool, + // a target sui amount for the pool, + // the extra sui amount will be staked to vsui + target_sui_amount: u64, + vsui_stake_pool: StakePool, + vsui_metadata: Metadata, + } + + // Event + struct FundUpdated has copy, drop { + original_sui_amount: u64, + current_sui_amount: u64, + vsui_balance_amount: u64, + // treasury_amount: u64, + target_sui_amount: u64, + } + + struct StakingTreasuryWithdrawn has copy, drop { + taken_vsui_balance_amount: u64, + equal_sui_balance_amount: u64 + } + + struct SuiKey has store, copy, drop {} + +} diff --git a/lending_core/sources/storage.move b/lending_core/sources/storage.move index 441d2ae..ce7e7a6 100644 --- a/lending_core/sources/storage.move +++ b/lending_core/sources/storage.move @@ -1,74 +1,240 @@ +#[allow(unused_field)] module lending_core::storage { + + use std::vector; use std::ascii::{String}; use sui::object::{UID}; use sui::table::{Table}; + use sui::clock::{Self, Clock}; + use sui::coin::{Self, CoinMetadata}; + use sui::tx_context::{TxContext}; + use sui_system::sui_system::{SuiSystemState}; + use lending_core::pool::{Self, Pool, PoolAdminCap}; + use lending_core::version::{Self}; + + struct OwnerCap has key, store { + id: UID, + } + + struct StorageAdminCap has key, store { + id: UID, + } - #[allow(unused_field)] struct Storage has key, store { id: UID, version: u64, - paused: bool, - reserves: Table, - reserves_count: u8, - users: vector
, + paused: bool, // Whether the pool is paused + reserves: Table, // Reserve list. like: {0: ReserveData, 1: ReserveData} + reserves_count: u8, // Total reserves count + users: vector
, // uset list, like [0x01, 0x02] user_info: Table } - #[allow(unused_field)] + // supply_balance & borrow_balance, It is used to keep track of all balance struct ReserveData has store { - id: u8, - oracle_id: u8, - coin_type: String, - is_isolated: bool, - supply_cap_ceiling: u256, - borrow_cap_ceiling: u256, - current_supply_rate: u256, - current_borrow_rate: u256, - current_supply_index: u256, - current_borrow_index: u256, - supply_balance: TokenBalance, - borrow_balance: TokenBalance, - last_update_timestamp: u64, + id: u8, // reserve index + oracle_id: u8, // The id from navi oracle, update from admin + coin_type: String, // The coin type, like 0x02::sui::SUI + is_isolated: bool, // THe isolated of the reserve, update from admin + supply_cap_ceiling: u256, // Total supply limit of reserve, update from admin + borrow_cap_ceiling: u256, // Total borrow percentage of reserve, update from admin + current_supply_rate: u256, // Current supply rates, update from protocol + current_borrow_rate: u256, // Current borrow rates, update from protocol + current_supply_index: u256, // The supply exchange rate, update from protocol + current_borrow_index: u256, // The borrow exchange rate, update from protocol + supply_balance: TokenBalance, // The total amount deposit inside the pool + borrow_balance: TokenBalance, // The total amount borrow inside the pool + last_update_timestamp: u64, // Last update time for reserve, update from protocol + // Loan-to-value, used to define the maximum amount of assets that can be borrowed against a given collateral ltv: u256, - treasury_factor: u256, - treasury_balance: u256, - borrow_rate_factors: BorrowRateFactors, - liquidation_factors: LiquidationFactors, + treasury_factor: u256, // The fee ratio, update from admin + treasury_balance: u256, // The fee balance, update from protocol + borrow_rate_factors: BorrowRateFactors, // Basic Configuration, rate and multiplier etc. + liquidation_factors: LiquidationFactors, // Liquidation configuration + // Reserved fields, no use for now reserve_field_a: u256, reserve_field_b: u256, reserve_field_c: u256, } - #[allow(unused_field)] struct UserInfo has store { collaterals: vector, loans: vector } - #[allow(unused_field)] + struct ReserveConfigurationMap has copy, store { + data: u256 + } + + struct UserConfigurationMap has copy, store { + data: u256 + } + struct TokenBalance has store { user_state: Table, total_supply: u256, } - #[allow(unused_field)] struct BorrowRateFactors has store { + // Base borrow rate of the asset base_rate: u256, multiplier: u256, jump_rate_multiplier: u256, + // Used to set community incentives reserve_factor: u256, optimal_utilization: u256 } - #[allow(unused_field)] struct LiquidationFactors has store { ratio: u256, bonus: u256, threshold: u256, } - + + struct Emode has store { + emodes_pair: Table, + user_emode_id: Table, + next_emode_id: u64, // each emode has a unique id, starting from 0 + } + + struct EmodeConfig has store { + assetA: EmodeAsset, + assetB: EmodeAsset, + isActive: bool + } + + struct EmodeAsset has store { + assetId: u8, + isCollateral: bool, + isDebt: bool, + ltv: u256, + lt: u256, + liquidation_bonus: u256 + } + + struct MarketInfo has store { + market_id: u64, + last_market_id: u64, + is_main_market: bool + } + + // Event + struct StorageConfiguratorSetting has copy, drop { + sender: address, + configurator: address, + value: bool, + } + + struct Paused has copy, drop { + paused: bool + } + + struct WithdrawTreasuryEvent has copy, drop { + sender: address, + recipient: address, + asset: u8, + amount: u256, + poolId: address, + before: u256, + after: u256, + index: u256, + } + + struct LiquidatorSet has copy, drop { + liquidator: address, + user: address, + is_liquidatable: bool + } + + struct ProtectedUserSet has copy, drop { + user: address, + is_protected: bool + } + + struct EmodePairCreated has copy, drop { + emode_id: u64, + assetA: u8, + assetB: u8, + } + + struct EmodeParamSet has copy, drop { + emode_id: u64, + asset: u8, + value: u256, + param_type: String, + } + + struct EmodeUserStateChanged has copy, drop { + user: address, + emode_id: u64, + is_entered: bool + } + + struct MarketCreated has copy, drop { market_id: u64 } + + struct BorrowWeightSet has copy, drop { + asset: u8, + weight: u64, + } + + struct BorrowWeightRemoved has copy, drop { asset: u8 } + + // === dynamic field keys === + struct DESIGNATED_LIQUIDATORS_KEY has copy, drop, store {} + + struct PROTECTED_LIQUIDATION_USERS_KEY has copy, drop, store {} + + // ------------------ Emode related functions ------------------ + struct EMODE_KEY has copy, drop, store {} + + // ------------------ Multiple markets related functions ------------------ + struct MARKET_KEY has copy, drop, store {} + + // ------------------ Borrow Weight related functions ------------------ + struct BORROW_WEIGHT_KEY has copy, drop, store {} + + native public fun when_not_paused(storage: &Storage); + + native public fun version_verification(storage: &Storage); + + native public entry fun version_migrate(_: &StorageAdminCap, storage: &mut Storage); + + native public entry fun init_reserve(_: &StorageAdminCap, pool_admin_cap: &PoolAdminCap, clock: &Clock, storage: &mut Storage, oracle_id: u8, is_isolated: bool, supply_cap_ceiling: u256, borrow_cap_ceiling: u256, base_rate: u256, optimal_utilization: u256, multiplier: u256, jump_rate_multiplier: u256, reserve_factor: u256, ltv: u256, treasury_factor: u256, liquidation_ratio: u256, liquidation_bonus: u256, liquidation_threshold: u256, coin_metadata: &CoinMetadata, ctx: &mut TxContext); + + ////////////////////////////////////////////////////////////////////////////////////////////// + // The methods required for protocol parameter updates // + ////////////////////////////////////////////////////////////////////////////////////////////// + native public entry fun set_pause(_: &OwnerCap, storage: &mut Storage, val: bool); + + native public fun set_supply_cap(_: &OwnerCap, storage: &mut Storage, asset: u8, supply_cap_ceiling: u256); + + native public fun set_borrow_cap(_: &OwnerCap, storage: &mut Storage, asset: u8, borrow_cap_ceiling: u256); + + native public fun set_ltv(_: &OwnerCap, storage: &mut Storage, asset: u8, ltv: u256); + + native public fun set_treasury_factor(_: &OwnerCap, storage: &mut Storage, asset: u8, treasury_factor: u256); + + native public fun set_base_rate(_: &OwnerCap, storage: &mut Storage, asset: u8, base_rate: u256); + + native public fun set_multiplier(_: &OwnerCap, storage: &mut Storage, asset: u8, multiplier: u256); + + native public fun set_jump_rate_multiplier(_: &OwnerCap, storage: &mut Storage, asset: u8, jump_rate_multiplier: u256); + + native public fun set_reserve_factor(_: &OwnerCap, storage: &mut Storage, asset: u8, reserve_factor: u256); + + native public fun set_optimal_utilization(_: &OwnerCap, storage: &mut Storage, asset: u8, optimal_utilization: u256); + + native public fun set_liquidation_ratio(_: &OwnerCap, storage: &mut Storage, asset: u8, liquidation_ratio: u256); + + native public fun set_liquidation_bonus(_: &OwnerCap, storage: &mut Storage, asset: u8, liquidation_bonus: u256); + + native public fun set_liquidation_threshold(_: &OwnerCap, storage: &mut Storage, asset: u8, liquidation_threshold: u256); + + ////////////////////////////////////////////////////////////////////////////////////////////// + // The methods required to get value // + ////////////////////////////////////////////////////////////////////////////////////////////// native public fun reserve_validation(storage: &Storage); - + native public fun pause(storage: &Storage): bool; native public fun get_reserves_count(storage: &Storage): u8; @@ -102,4 +268,50 @@ module lending_core::storage { native public fun get_borrow_rate_factors(storage: &mut Storage, asset: u8): (u256, u256, u256, u256, u256); native public fun get_liquidation_factors(storage: &mut Storage, asset: u8): (u256, u256, u256); -} \ No newline at end of file + + native public fun withdraw_treasury(_: &StorageAdminCap, pool_admin_cap: &PoolAdminCap, storage: &mut Storage, asset: u8, pool: &mut Pool, amount: u64, recipient: address, ctx: &mut TxContext); + + native public fun withdraw_treasury_v2(_: &StorageAdminCap, pool_admin_cap: &PoolAdminCap, storage: &mut Storage, asset: u8, pool: &mut Pool, amount: u64, recipient: address, system_state: &mut SuiSystemState, ctx: &mut TxContext); + + native public fun destory_user(_: &StorageAdminCap, _storage: &mut Storage); + + native public fun mint_owner_cap(_: &StorageAdminCap, recipient: address, ctx: &mut TxContext); + + native public fun is_liquidatable(storage: &mut Storage, liquidator: address, user: address): bool; + + native public fun when_liquidatable(storage: &mut Storage, liquidator: address, user: address); + + native public fun init_emode_for_main_market(_: &StorageAdminCap, storage: &mut Storage, ctx: &mut TxContext); + + native public fun verify_emode_support(storage: &Storage, user: address, asset_id: u8, check_is_collateral: bool, check_is_debt: bool); + + native public fun is_passed_emode_restrictions(storage: &Storage, user: address, asset_id: u8, check_is_collateral: bool, check_is_debt: bool): bool; + + native public fun is_in_emode(storage: &Storage, user: address): bool; + + native public fun get_user_emode_id(storage: &Storage, user: address): u64; + + // return (ltvA, ltA, liquidation_bonusA, isCollateralA, isDebtA, ltvB, ltB, liquidation_bonusB, isCollateralB, isDebtB, isActive) + native public fun get_emode_info(storage: &Storage, emode_id: u64): (u256, u256, u256, bool, bool, u256, u256, u256, bool, bool, bool); + + // return (ltv, lt, liquidation_bonus) + native public fun get_emode_asset_info(storage: &Storage, emode_id: u64, asset: u8): (u256, u256, u256); + + native public fun init_for_main_market(_: &StorageAdminCap, storage: &mut Storage); + + native public fun get_market_id(storage: &Storage): u64; + + // return (market_id, last_market_id, is_main_market) + native public fun get_storage_market_info(storage: &Storage): (u64, u64, bool); + + native public fun verify_market_storage_pool(storage: &Storage, pool: &Pool); + + native public fun init_borrow_weight_for_main_market(_: &StorageAdminCap, storage: &mut Storage, ctx: &mut TxContext); + + native public fun get_borrow_weight(storage: &Storage, asset: u8): u64; + + // legacy: should be test only, but it's already public in the old version + // #[test_only] + native public fun get_reserve_for_testing(storage: &Storage, asset: u8): (&ReserveData); + +} diff --git a/lending_core/sources/validation.move b/lending_core/sources/validation.move index 07bd54b..c5d88e5 100644 --- a/lending_core/sources/validation.move +++ b/lending_core/sources/validation.move @@ -1,13 +1,31 @@ module lending_core::validation { - use lending_core::storage::{Storage}; + use lending_core::storage::{Self, Storage}; + + /** + * Title: Validates a deposit action + * storage: - + * asset: - + * amount: + * - The decimals of ETH is 9 + * - Total collateral is 1.2ETH --> amount = 1.2 * 1e9 = 1200000000 + */ native public fun validate_deposit(storage: &mut Storage, asset: u8, amount: u256); native public fun validate_withdraw(storage: &mut Storage, asset: u8, amount: u256); + /** + * Title: Validates borrow action + * storage: - + * asset: - + * amount: + * - The decimals of ETH is 9 + * - borrow amount is 1.2ETH --> amount = 1.2 * 1e9 = 1200000000 + */ native public fun validate_borrow(storage: &mut Storage, asset: u8, amount: u256); native public fun validate_repay(storage: &mut Storage, asset: u8, amount: u256); native public fun validate_liquidate(storage: &mut Storage, debt_asset: u8, collateral_asset: u8, amount: u256); -} \ No newline at end of file + +} diff --git a/lending_core/sources/version.move b/lending_core/sources/version.move index 9d376c7..cfcd351 100644 --- a/lending_core/sources/version.move +++ b/lending_core/sources/version.move @@ -1,7 +1,9 @@ module lending_core::version { + native public fun this_version(): u64; native public fun next_version(): u64; native public fun pre_check_version(v: u64); -} \ No newline at end of file + +} diff --git a/math/Move.toml b/math/Move.toml index 154bc80..8ade957 100644 --- a/math/Move.toml +++ b/math/Move.toml @@ -1,7 +1,6 @@ [package] name = "math" version = "0.0.1" -published-at = "0x66aa3335901ce7e04b85ed6597ee42d4b479f7110bf98e8ebd474fa32a0027e1" [dependencies.Sui] git = "https://github.com/MystenLabs/sui.git" @@ -10,4 +9,4 @@ rev = "mainnet" [addresses] sui = "0x2" -math = "0x66aa3335901ce7e04b85ed6597ee42d4b479f7110bf98e8ebd474fa32a0027e1" \ No newline at end of file +math = "0x0" \ No newline at end of file diff --git a/oracle/Move.lock b/oracle/Move.lock index bebd499..8d843ce 100644 --- a/oracle/Move.lock +++ b/oracle/Move.lock @@ -1,71 +1,209 @@ -# @generated by Move, please check-in and do not edit manually. +# Generated by move; do not edit +# This file should be checked in. [move] -version = 2 -manifest_digest = "026761BD43C951CADA14BEC8CD86C95E9DFEF2D3F188EDDA71F84442C4AB8047" -deps_digest = "060AD7E57DFB13104F21BE5F5C3759D03F0553FC3229247D9A7A6B45F50D03A3" -dependencies = [ - { name = "Pyth" }, - { name = "Sui" }, - { name = "SupraOracle" }, -] - -[[move.package]] -name = "MoveStdlib" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "mainnet", subdir = "crates/sui-framework/packages/move-stdlib" } - -[[move.package]] -name = "Pyth" -source = { git = "https://github.com/naviprotocol/pyth-crosschain.git", rev = "navi-forked", subdir = "target_chains/sui/contracts" } - -dependencies = [ - { name = "Sui" }, - { name = "Wormhole" }, -] - -[[move.package]] -name = "Sui" -source = { git = "https://github.com/MystenLabs/sui.git", rev = "mainnet", subdir = "crates/sui-framework/packages/sui-framework" } - -dependencies = [ - { name = "MoveStdlib" }, -] - -[[move.package]] -name = "SupraOracle" -source = { git = "https://github.com/naviprotocol/dora-interface.git", rev = "main", subdir = "sui/mainnet/supra_holder" } - -dependencies = [ - { name = "Sui" }, - { name = "supra_validator" }, -] - -[[move.package]] -name = "Wormhole" -source = { git = "https://github.com/naviprotocol/wormhole.git", rev = "navi-forked", subdir = "sui/wormhole" } - -dependencies = [ - { name = "Sui" }, -] - -[[move.package]] -name = "supra_utils" -source = { git = "https://github.com/naviprotocol/dora-interface.git", rev = "main", subdir = "sui/mainnet/supra_utils" } - -dependencies = [ - { name = "Sui" }, -] - -[[move.package]] -name = "supra_validator" -source = { git = "https://github.com/naviprotocol/dora-interface.git", rev = "main", subdir = "sui/mainnet/supra_validator" } - -dependencies = [ - { name = "Sui" }, - { name = "supra_utils" }, -] - -[move.toolchain-version] -compiler-version = "1.27.2" -edition = "legacy" -flavor = "sui" +version = 4 + +[pinned.mainnet.MoveStdlib] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "b9149cbf0b2cb9ae5ed830407a9b48c7ae3fd36c" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.MoveStdlib_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.MoveStdlib_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.MoveStdlib_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "mainnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.mainnet.Pyth] +source = { git = "https://github.com/naviprotocol/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "1880b24c6acfaac101747f863c5047fff9adaa0f" } +use_environment = "mainnet" +manifest_digest = "C981BFE5D31B50DB795278F9617725C1C2AEDFE52970A2E02D2B5636175470AB" +deps = { Sui = "Sui_1", Wormhole = "Wormhole" } + +[pinned.mainnet.PythProCompatible] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "mainnet" +manifest_digest = "3D2B5BBF2058F3C9DCA3527CC2486C518124687B60479CA9875E5475652B7BBC" +deps = { Sui = "Sui_2", WormholeSimpleMajority = "WormholeSimpleMajority" } + +[pinned.mainnet.Sui] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "b9149cbf0b2cb9ae5ed830407a9b48c7ae3fd36c" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib" } + +[pinned.mainnet.Sui_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib_1" } + +[pinned.mainnet.Sui_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib_2" } + +[pinned.mainnet.Sui_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "mainnet" +manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195" +deps = { MoveStdlib = "MoveStdlib_3" } + +[pinned.mainnet.SupraOracle] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_holder", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "mainnet" +manifest_digest = "CDD606D609F32BF36A2C06E7DB0E6BBBA82B7EC29C58D217D0AFCED1E87ED550" +deps = { Sui = "Sui_1", supra_validator = "supra_validator" } + +[pinned.mainnet.Switchboard] +source = { git = "https://github.com/naviprotocol/navi-smart-contracts.git", subdir = "switchboard_sui/on_demand", rev = "473b0934235d6dc1357fa4309308167c6d175fd1" } +use_environment = "mainnet" +manifest_digest = "BA49968BFF7C4A4D9F013B59535CF8B89D935A7C6D63C121606B1FE844829B72" +deps = { Sui = "Sui_3" } + +[pinned.mainnet.Wormhole] +source = { git = "https://github.com/naviprotocol/wormhole.git", subdir = "sui/wormhole", rev = "7749aff1380b0f63743d36856a5934de606483ba" } +use_environment = "mainnet" +manifest_digest = "3876920E3F5449B657525E749B996C31141507452514AF2E259F5441554DCDDF" +deps = { Sui = "Sui_1" } + +[pinned.mainnet.WormholeSimpleMajority] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/vendor/wormhole_simple_majority/wormhole", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "mainnet" +manifest_digest = "0D766A0380B75080707CFA6099AF469A2E502B0D9DC334A9E9983B391C5555D9" +deps = { Sui = "Sui_2" } + +[pinned.mainnet.oracle] +source = { root = true } +use_environment = "mainnet" +manifest_digest = "E04AD78C45C58C917E5B839EC9B849FBD76C699C2EF25F105518CEF9FE6CDA8C" +deps = { SupraOracle = "SupraOracle", pyth = "Pyth", pyth_pro_compatible = "PythProCompatible", std = "MoveStdlib", sui = "Sui", switchboard = "Switchboard" } + +[pinned.mainnet.supra_utils] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_utils", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "mainnet" +manifest_digest = "3876920E3F5449B657525E749B996C31141507452514AF2E259F5441554DCDDF" +deps = { Sui = "Sui_1" } + +[pinned.mainnet.supra_validator] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_validator", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "mainnet" +manifest_digest = "6972115A9F4DCD60D13D7BB34F2D42245F8743B737EA8651F3DF6669BC3D6C93" +deps = { Sui = "Sui_1", supra_utils = "supra_utils" } + +[pinned.testnet.MoveStdlib] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "d50b78880fdacb1bbde92e6974ed71a7650c1090" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.testnet.MoveStdlib_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.testnet.MoveStdlib_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.testnet.MoveStdlib_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "testnet" +manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" +deps = {} + +[pinned.testnet.Pyth] +source = { git = "https://github.com/naviprotocol/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "1880b24c6acfaac101747f863c5047fff9adaa0f" } +use_environment = "testnet" +manifest_digest = "485F78616CB77F1A3EA3FC932926DF0B5411D2758EE2BAFA4C4652A4EF06D29B" +deps = { Sui = "Sui_1", Wormhole = "Wormhole" } + +[pinned.testnet.PythProCompatible] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/contracts", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "testnet" +manifest_digest = "AEAC3FAD5DCF925755E55B4498F4CED3B564F87B638049EF0A7C4E9F2EA7E9EC" +deps = { Sui = "Sui_2", WormholeSimpleMajority = "WormholeSimpleMajority" } + +[pinned.testnet.Sui] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "d50b78880fdacb1bbde92e6974ed71a7650c1090" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib" } + +[pinned.testnet.Sui_1] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "433212f8f2768ac22dd412229c970b8a5281d4e5" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib_1" } + +[pinned.testnet.Sui_2] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "041c5f2bae2fe52079e44b70514333532d69f4e6" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib_2" } + +[pinned.testnet.Sui_3] +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "027e13b2c14022b58067bd536c7e4f2afff72164" } +use_environment = "testnet" +manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" +deps = { MoveStdlib = "MoveStdlib_3" } + +[pinned.testnet.SupraOracle] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_holder", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "testnet" +manifest_digest = "9C02A35D78AABF65198AAF05ECD1263DA17CF8CDC9057DBD530C7A2EEC5B1DF4" +deps = { Sui = "Sui_1", supra_validator = "supra_validator" } + +[pinned.testnet.Switchboard] +source = { git = "https://github.com/naviprotocol/navi-smart-contracts.git", subdir = "switchboard_sui/on_demand", rev = "473b0934235d6dc1357fa4309308167c6d175fd1" } +use_environment = "testnet" +manifest_digest = "DEE42C89BB3F8EC67C17BC4AE0CEBE14A28F4FA787E857046EAF0FA38D556496" +deps = { Sui = "Sui_3" } + +[pinned.testnet.Wormhole] +source = { git = "https://github.com/naviprotocol/wormhole.git", subdir = "sui/wormhole", rev = "7749aff1380b0f63743d36856a5934de606483ba" } +use_environment = "testnet" +manifest_digest = "C2772B976EC6A56C32071C116C869B6B810C731713A3E79642606E99AE1F55DA" +deps = { Sui = "Sui_1" } + +[pinned.testnet.WormholeSimpleMajority] +source = { git = "https://github.com/pyth-network/pyth-crosschain.git", subdir = "target_chains/sui/vendor/wormhole_simple_majority/wormhole", rev = "aa291266173173480efef77b9454f2dbc2b4fd62" } +use_environment = "testnet" +manifest_digest = "6996F1AB8CD448FFBA142C085C488FE8A46B485E61E38A1891EFA52B30D9C12E" +deps = { Sui = "Sui_2" } + +[pinned.testnet.oracle] +source = { root = true } +use_environment = "testnet" +manifest_digest = "B76685B606F186A6557ECD98B4FC6988E9BE0DC3E97F5875DEEDD609D7E9D168" +deps = { SupraOracle = "SupraOracle", pyth = "Pyth", pyth_pro_compatible = "PythProCompatible", std = "MoveStdlib", sui = "Sui", switchboard = "Switchboard" } + +[pinned.testnet.supra_utils] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_utils", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "testnet" +manifest_digest = "C2772B976EC6A56C32071C116C869B6B810C731713A3E79642606E99AE1F55DA" +deps = { Sui = "Sui_1" } + +[pinned.testnet.supra_validator] +source = { git = "https://github.com/naviprotocol/dora-interface.git", subdir = "sui/mainnet/supra_validator", rev = "ef26a08b045389efd2a1df39d61e064cb2252713" } +use_environment = "testnet" +manifest_digest = "20910F73E6DB180B11201B71A872B16AED4CFEF8AAE1428E33839CB5860A569E" +deps = { Sui = "Sui_1", supra_utils = "supra_utils" } diff --git a/oracle/Move.toml b/oracle/Move.toml index b5e739a..4f88fb6 100644 --- a/oracle/Move.toml +++ b/oracle/Move.toml @@ -1,23 +1,24 @@ [package] name = "oracle" version = "0.0.1" -published-at = "0xc2d49bf5e75d2258ee5563efa527feb6155de7ac6f6bf025a23ee88cd12d5a83" - -[dependencies.Sui] -git = "https://github.com/MystenLabs/sui.git" -subdir = "crates/sui-framework/packages/sui-framework" -rev = "mainnet" [dependencies.SupraOracle] git = "https://github.com/naviprotocol/dora-interface.git" subdir = "sui/mainnet/supra_holder" rev = "main" -[dependencies.Pyth] +[dependencies.pyth] git = "https://github.com/naviprotocol/pyth-crosschain.git" subdir = "target_chains/sui/contracts" rev = "navi-forked" -[addresses] -sui = "0x02" -oracle = "0xca441b44943c16be0e6e23c5a955bb971537ea3289ae8016fbf33fffe1fd210f" +[dependencies.pyth_pro_compatible] +git = "https://github.com/pyth-network/pyth-crosschain.git" +subdir = "target_chains/sui/contracts" +rev = "sui-pro-compatible-contract-mainnet" +rename-from = "pyth" + +[dependencies.switchboard] +git = "https://github.com/naviprotocol/navi-smart-contracts.git" +subdir = "switchboard_sui/on_demand" +rev = "main" diff --git a/oracle/Published.toml b/oracle/Published.toml new file mode 100644 index 0000000..1a8ae6e --- /dev/null +++ b/oracle/Published.toml @@ -0,0 +1,9 @@ +# Generated by Move +# This file contains metadata about published versions of this package in different environments +# This file SHOULD be committed to source control + +[published.mainnet] +chain-id = "35834a8a" +published-at = "0x4837ae94425107554c8847721cf9954c1ad8e10520433b9e37dc11c507148bea" +original-id = "0xca441b44943c16be0e6e23c5a955bb971537ea3289ae8016fbf33fffe1fd210f" +version = 5 diff --git a/oracle/sources/adaptor_pyth.move b/oracle/sources/adaptor_pyth.move index fcc3be9..edf6702 100644 --- a/oracle/sources/adaptor_pyth.move +++ b/oracle/sources/adaptor_pyth.move @@ -1,22 +1,46 @@ module oracle::adaptor_pyth { + use sui::clock::{Clock}; use pyth::state::{State}; use pyth::price_info::{PriceInfoObject}; + use pyth_pro_compatible::state::{State as ProState}; + use pyth_pro_compatible::price_info::{PriceInfoObject as ProPriceInfoObject}; - - // get_price_native: Just return the price/decimal(expo)/timestamp from pyth oracle + // Legacy Pyth (0x8d97..) is retired after the Pyth Core upgrade (2026-07-31). + // Each legacy function below is kept as an abort stub for upgrade compatibility, + // with its pro-compatible replacement (_v2) directly underneath. + #[allow(unused_variable)] native public fun get_price_native(clock: &Clock, pyth_state: &State, pyth_price_info: &PriceInfoObject): (u64, u64, u64); - // get_price_unsafe_native: return the price(uncheck timestamp)/decimal(expo)/timestamp from pyth oracle + // get_price_native_v2: Just return the price/decimal(expo)/timestamp from pyth oracle + native public fun get_price_native_v2(clock: &Clock, pyth_state: &ProState, pyth_price_info: &ProPriceInfoObject): (u64, u64, u64); + + #[allow(unused_variable)] native public fun get_price_unsafe_native(pyth_price_info: &PriceInfoObject): (u64, u64, u64); - // get_price_to_target_decimal: return the target decimal price and timestamp + // get_price_unsafe_native_v2: return the price(uncheck timestamp)/decimal(expo)/timestamp from pyth oracle + native public fun get_price_unsafe_native_v2(pyth_price_info: &ProPriceInfoObject): (u64, u64, u64); + + #[allow(unused_variable)] native public fun get_price_to_target_decimal(clock: &Clock, pyth_state: &State, pyth_price_info: &PriceInfoObject, target_decimal: u8): (u256, u64); - // get_price_unsafe_to_target_decimal: return the target decimal price(uncheck timestamp) and timestamp + // get_price_to_target_decimal_v2: return the target decimal price and timestamp + native public fun get_price_to_target_decimal_v2(clock: &Clock, pyth_state: &ProState, pyth_price_info: &ProPriceInfoObject, target_decimal: u8): (u256, u64); + + #[allow(unused_variable)] native public fun get_price_unsafe_to_target_decimal(pyth_price_info: &PriceInfoObject, target_decimal: u8): (u256, u64); + // get_price_unsafe_to_target_decimal_v2: return the target decimal price(uncheck timestamp) and timestamp + native public fun get_price_unsafe_to_target_decimal_v2(pyth_price_info: &ProPriceInfoObject, target_decimal: u8): (u256, u64); + + #[allow(unused_variable)] native public fun get_identifier_to_vector(price_info_object: &PriceInfoObject): vector; + native public fun get_identifier_to_vector_v2(price_info_object: &ProPriceInfoObject): vector; + + #[allow(unused_variable)] native public fun get_price_info_object_id(pyth_state: &State, price_feed_id: address): address; -} \ No newline at end of file + + native public fun get_price_info_object_id_v2(pyth_state: &ProState, price_feed_id: address): address; + +} diff --git a/oracle/sources/adaptor_supra.move b/oracle/sources/adaptor_supra.move index 9d2788e..4ab034c 100644 --- a/oracle/sources/adaptor_supra.move +++ b/oracle/sources/adaptor_supra.move @@ -1,13 +1,16 @@ // Source Interface: https://gb-docs.supraoracles.com/docs/data-feeds/pull-model module oracle::adaptor_supra { + use SupraOracle::SupraSValueFeed::{OracleHolder}; // get_price_native: Just return the price/decimal/timestamp from supra oracle native public fun get_price_native(supra_oracle_holder: &OracleHolder, pair: u32): (u128, u16, u128); + // get_price: return the target decimal price and timestamp native public fun get_price_to_target_decimal(supra_oracle_holder: &OracleHolder, pair: u32, target_decimal: u8): (u256, u64); native public fun pair_id_to_vector(v: u32): vector; native public fun vector_to_pair_id(v: vector): u32; -} \ No newline at end of file + +} diff --git a/oracle/sources/adaptor_swtichboard.move b/oracle/sources/adaptor_swtichboard.move new file mode 100644 index 0000000..b56ea64 --- /dev/null +++ b/oracle/sources/adaptor_swtichboard.move @@ -0,0 +1,14 @@ +module oracle::adaptor_switchboard { + + use switchboard::aggregator::{Self, Aggregator}; + + native public fun get_price_native(aggregator: &Aggregator): (u128, u8, u64); + + // get_price_to_target_decimal: return the target decimal price and timestamp + native public fun get_price_to_target_decimal(aggregator: &Aggregator, target_decimal: u8): (u256, u64); + + native public fun get_identifier_to_vector(aggregator: &Aggregator): vector; + + native public fun get_aggregator_id(aggregator: &Aggregator): address; + +} diff --git a/oracle/sources/config.move b/oracle/sources/config.move index d449036..edd5e17 100644 --- a/oracle/sources/config.move +++ b/oracle/sources/config.move @@ -1,11 +1,13 @@ module oracle::config { + + use std::vector; use std::ascii::{String}; use sui::object::{UID}; use sui::table::{Table}; + use oracle::oracle_version::{Self as version}; use oracle::oracle_provider::{OracleProvider, OracleProviderConfig}; // Structs - #[allow(unused_field)] struct OracleConfig has key, store { id: UID, version: u64, @@ -14,7 +16,6 @@ module oracle::config { feeds: Table, } - #[allow(unused_field)] struct PriceFeed has store { id: UID, enable: bool, // when the decentralized price of a certain token goes wrong, it can be disable @@ -35,12 +36,141 @@ module oracle::config { history: History, } - #[allow(unused_field)] struct History has copy, store { price: u256, updated_time: u64, } + // Events + struct ConfigCreated has copy, drop { + sender: address, + id: address, + } + + struct ConfigSetPaused has copy, drop { + config: address, + value: bool, + before_value: bool, + } + + struct PriceFeedCreated has copy, drop { + sender: address, + config: address, + feed_id: address, + } + + struct PriceFeedSetEnable has copy, drop { + config: address, + feed_id: address, + value: bool, + before_value: bool, + } + + struct PriceFeedSetMaxTimestampDiff has copy, drop { + config: address, + feed_id: address, + value: u64, + before_value: u64, + } + + struct PriceFeedSetPriceDiffThreshold1 has copy, drop { + config: address, + feed_id: address, + value: u64, + before_value: u64, + } + + struct PriceFeedSetPriceDiffThreshold2 has copy, drop { + config: address, + feed_id: address, + value: u64, + before_value: u64, + } + + struct PriceFeedSetMaxDurationWithinThresholds has copy, drop { + config: address, + feed_id: address, + value: u64, + before_value: u64, + } + + struct PriceFeedSetMaximumAllowedSpanPercentage has copy, drop { + config: address, + feed_id: address, + value: u64, + before_value: u64, + } + + struct PriceFeedSetMaximumEffectivePrice has copy, drop { + config: address, + feed_id: address, + value: u256, + before_value: u256, + } + + struct PriceFeedSetMinimumEffectivePrice has copy, drop { + config: address, + feed_id: address, + value: u256, + before_value: u256, + } + + struct PriceFeedSetOracleId has copy, drop { + config: address, + feed_id: address, + value: u8, + before_value: u8, + } + + struct SetOracleProvider has copy, drop { + config: address, + feed_id: address, + is_primary: bool, // primary: true, secondary: false + provider: String, + before_provider: String, + } + + struct OracleProviderConfigCreated has copy, drop { + config: address, + feed_id: address, + provider: String, + pair_id: vector, + } + + struct OracleProviderConfigSetPairId has copy, drop { + config: address, + feed_id: address, + provider: String, + value: vector, + before_value: vector, + } + + struct OracleProviderConfigSetEnable has copy, drop { + config: address, + feed_id: address, + provider: String, + value: bool, + before_value: bool, + } + + struct PriceFeedSetHistoricalPriceTTL has copy, drop { + config: address, + feed_id: address, + value: u64, + before_value: u64, + } + + struct PriceFeedDiffThreshold2TimerUpdated has copy, drop { + feed_id: address, + updated_at: u64, + } + + struct PriceFeedDiffThreshold2TimerReset has copy, drop { + feed_id: address, + started_at: u64, + } + + // Friend Functions() native public fun version_verification(cfg: &OracleConfig); native public fun is_price_feed_exists(cfg: &OracleConfig, oracle_id: u8): bool; @@ -142,6 +272,7 @@ module oracle::config { native public fun get_updated_time_from_history(history: &History): u64; + // native public fun is_secondary_oracle_available(price_feed: &PriceFeed): bool; -} +} diff --git a/oracle/sources/oracle.move b/oracle/sources/oracle.move index 500b3fb..06f8b47 100644 --- a/oracle/sources/oracle.move +++ b/oracle/sources/oracle.move @@ -1,9 +1,21 @@ +#[allow(lint(self_transfer))] module oracle::oracle { + + use std::vector; use sui::object::{UID}; use sui::table::{Table}; - use sui::clock::{Clock}; + use sui::clock::{Self, Clock}; + use sui::tx_context::{TxContext}; + use oracle::oracle_version::{Self as version}; + + struct OracleAdminCap has key, store { + id: UID, + } + + struct OracleFeederCap has key, store { + id: UID, + } - #[allow(unused_field)] struct PriceOracle has key { id: UID, version: u64, @@ -11,14 +23,42 @@ module oracle::oracle { price_oracles: Table, } - #[allow(unused_field)] struct Price has store { value: u256, decimal: u8, timestamp: u64 } + // Events + struct PriceUpdated has copy, drop { + price_oracle: address, + id: u8, + price: u256, + last_price: u256, + update_at: u64, + last_update_at: u64, + } + + native public fun create_feeder(_: &OracleAdminCap, ctx: &mut TxContext); + + #[allow(unused_variable, unused_mut_parameter)] + native entry fun version_migrate(_: &OracleAdminCap, oracle: &mut PriceOracle); + + native public entry fun set_update_interval(_: &OracleAdminCap, price_oracle: &mut PriceOracle, update_interval: u64); + + native public entry fun register_token_price(_: &OracleAdminCap, clock: &Clock, price_oracle: &mut PriceOracle, oracle_id: u8, token_price: u256, price_decimal: u8); + + // function to externally update prices by the feeder + native public entry fun update_token_price(_: &OracleFeederCap, clock: &Clock, price_oracle: &mut PriceOracle, oracle_id: u8, token_price: u256); + + native public entry fun update_token_price_batch(cap: &OracleFeederCap, clock: &Clock, price_oracle: &mut PriceOracle, oracle_ids: vector, token_prices: vector); + native public fun get_token_price(clock: &Clock, price_oracle: &PriceOracle, oracle_id: u8): (bool, u256, u8); - native public fun safe_decimal(price_oracle: &mut PriceOracle, oracle_id: u8): u8; + native public fun price_object(price_oracle: &PriceOracle, oracle_id: u8): &Price; + + native public fun decimal(price_oracle: &mut PriceOracle, oracle_id: u8): u8; + + native public fun safe_decimal(price_oracle: &PriceOracle, oracle_id: u8): u8; + } diff --git a/oracle/sources/oracle_constants.move b/oracle/sources/oracle_constants.move index c8cfb18..af1f4e2 100644 --- a/oracle/sources/oracle_constants.move +++ b/oracle/sources/oracle_constants.move @@ -1,36 +1,37 @@ module oracle::oracle_constants { // Critical level: it is issued when the price difference exceeds x2 - public fun level_critical(): u8 { 0 } + public fun level_critical(): u8 {0} // Major level: it is issued when the price difference exceeds x1 and does not exceed x2, but it lasts too long - public fun level_major(): u8 { 1 } + public fun level_major(): u8 {1} // Warning level: it is issued when the price difference exceeds x1 and does not exceed x2 and the duration is within an acceptable range - public fun level_warning(): u8 { 2 } + public fun level_warning(): u8 {2} - public fun level_normal(): u8 { 3 } + public fun level_normal(): u8 {3} // After the price is filtered by the strategy, the available prices are empty. Highest level - public fun no_available_prices(): u8 { 0 } + public fun no_available_prices(): u8 {0} // After the price is filtered by the strategy, the unavailable price list is not empty. Warning level - public fun unavailable_prices(): u8 { 1 } + public fun unavailable_prices(): u8 {1} - public fun primary_type(): u8 { 0 } + public fun primary_type(): u8 {0} - public fun secondary_type(): u8 { 1 } + public fun secondary_type(): u8 {1} - public fun both_type(): u8 { 2 } + public fun both_type(): u8 {2} - public fun multiple(): u64 { 10000 } + public fun multiple(): u64 {10000} - public fun version(): u64 { 2 } + public fun version(): u64 {4} - public fun default_update_interval(): u64 {30000} // 30s + public fun default_update_interval(): u64 {30000} + // 30s public fun default_decimal_limit(): u8 {16} - public fun success(): u64 {1} + public fun success(): u64 {1} -} \ No newline at end of file +} diff --git a/oracle/sources/oracle_dynamic_getter.move b/oracle/sources/oracle_dynamic_getter.move index 0f5df80..85d0986 100644 --- a/oracle/sources/oracle_dynamic_getter.move +++ b/oracle/sources/oracle_dynamic_getter.move @@ -1,10 +1,20 @@ module oracle::oracle_dynamic_getter { - use sui::clock::{Clock}; + + use sui::clock::{Self, Clock}; use oracle::oracle::{PriceOracle}; use oracle::config::{OracleConfig}; use SupraOracle::SupraSValueFeed::{OracleHolder}; use pyth::price_info::{PriceInfoObject}; + use pyth_pro_compatible::price_info::{PriceInfoObject as ProPriceInfoObject}; + use switchboard::aggregator::{Aggregator}; - #[allow(unused_assignment)] + // Deprecated: legacy Pyth deployment is retired after the Pyth Core upgrade (2026-07-31) + #[allow(unused_variable)] native public fun get_dynamic_single_price(clock: &Clock, oracle_config: &OracleConfig, price_oracle: &PriceOracle, supra_oracle_holder: &OracleHolder, pyth_price_info: &PriceInfoObject, feed_address: address): (u64, u256); -} \ No newline at end of file + + /// a dynamic function to fetch a latest price without actually updating the price + /// return (result, price) + #[allow(unused_assignment)] + native public fun get_dynamic_single_price_v2(clock: &Clock, oracle_config: &OracleConfig, price_oracle: &PriceOracle, supra_oracle_holder: &OracleHolder, pyth_price_info: &ProPriceInfoObject, switchboard_aggregator: &Aggregator, feed_address: address): (u64, u256); + +} diff --git a/oracle/sources/oracle_error.move b/oracle/sources/oracle_error.move index af35a5e..3692a29 100644 --- a/oracle/sources/oracle_error.move +++ b/oracle/sources/oracle_error.move @@ -1,23 +1,43 @@ module oracle::oracle_error { + public fun price_feed_not_found(): u64 {6000} + public fun price_feed_already_exists(): u64 {6001} + public fun provider_config_not_found(): u64 {6002} + public fun provider_is_being_used_in_primary(): u64 {6003} + public fun oracle_config_already_exists(): u64 {6004} + public fun oracle_provider_config_not_found(): u64 {6005} + public fun paused(): u64 {6006} + public fun pair_not_match(): u64 {6007} + public fun price_oracle_not_found(): u64 {6008} + public fun invalid_oracle_provider(): u64 {6009} + public fun price_length_not_match(): u64 {6010} + public fun non_existent_oracle(): u64 {6011} + public fun oracle_already_exist(): u64 {6012} + public fun oracle_provider_disabled(): u64 {6013} + public fun invalid_value(): u64 {6014} + public fun invalid_price_diff(): u64 {6015} + public fun no_available_price(): u64 {6016} + public fun invalid_final_price(): u64 {6017} public fun incorrect_version(): u64 {6200} + public fun not_available_version(): u64 {6201} + } diff --git a/oracle/sources/oracle_manage.move b/oracle/sources/oracle_manage.move index 2b1d3fa..19f1273 100644 --- a/oracle/sources/oracle_manage.move +++ b/oracle/sources/oracle_manage.move @@ -1,2 +1,62 @@ module oracle::oracle_manage { -} \ No newline at end of file + + use sui::tx_context::{TxContext}; + use oracle::oracle::{OracleAdminCap, PriceOracle}; + use oracle::config::{OracleConfig}; + use oracle::oracle_provider::{OracleProvider}; + + native public fun create_config(_: &OracleAdminCap, ctx: &mut TxContext); + + native public fun version_migrate(cap: &OracleAdminCap, oracle_config: &mut OracleConfig, price_oracle: &mut PriceOracle); + + native public fun set_pause(_: &OracleAdminCap, oracle_config: &mut OracleConfig, value: bool); + + native public fun create_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, oracle_id: u8, max_timestamp_diff: u64, price_diff_threshold1: u64, price_diff_threshold2: u64, max_duration_within_thresholds: u64, maximum_allowed_span_percentage: u64, maximum_effective_price: u256, minimum_effective_price: u256, historical_price_ttl: u64, ctx: &mut TxContext); + + native public fun set_enable_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: bool); + + native public fun set_max_timestamp_diff_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u64); + + native public fun set_price_diff_threshold1_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u64); + + native public fun set_price_diff_threshold2_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u64); + + native public fun set_max_duration_within_thresholds_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u64); + + native public fun set_maximum_allowed_span_percentage_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u64); + + native public fun set_maximum_effective_price_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u256); + + native public fun set_minimum_effective_price_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u256); + + native public fun set_historical_price_ttl_to_price_feed(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, value: u64); + + native public fun create_pyth_oracle_provider_config(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, pair_id: vector, enable: bool); + + native public fun set_pyth_price_oracle_provider_pair_id(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, pair_id: vector); + + native public fun enable_pyth_oracle_provider(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address); + + native public fun disable_pyth_oracle_provider(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address); + + native public fun create_supra_oracle_provider_config(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, pair_id: u32, enable: bool); + + native public fun set_supra_price_source_pair_id(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, pair_id: vector); + + native public fun enable_supra_oracle_provider(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address); + + native public fun disable_supra_oracle_provider(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address); + + native public fun create_switchboard_oracle_provider_config(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, pair_id: vector, enable: bool); + + native public fun set_switchboard_price_source_pair_id(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address, pair_id: vector); + + native public fun enable_switchboard_oracle_provider(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address); + + native public fun disable_switchboard_oracle_provider(_: &OracleAdminCap, oracle_config: &mut OracleConfig, feed_id: address); + + native public fun set_primary_oracle_provider(_: &OracleAdminCap, cfg: &mut OracleConfig, feed_id: address, provider: OracleProvider); + + native public fun set_secondary_oracle_provider(_: &OracleAdminCap, cfg: &mut OracleConfig, feed_id: address, provider: OracleProvider); + +} diff --git a/oracle/sources/oracle_pro.move b/oracle/sources/oracle_pro.move index 1f516b1..b8b832b 100644 --- a/oracle/sources/oracle_pro.move +++ b/oracle/sources/oracle_pro.move @@ -1,12 +1,68 @@ module oracle::oracle_pro { - use sui::clock::{Clock}; - use oracle::oracle_provider::{OracleProviderConfig}; + + use std::ascii::{String}; + use sui::clock::{Self, Clock}; + use oracle::oracle_provider::{Self as provider, OracleProviderConfig}; use oracle::oracle::{PriceOracle}; use oracle::config::{OracleConfig}; use SupraOracle::SupraSValueFeed::{OracleHolder}; use pyth::price_info::{PriceInfoObject}; + use pyth_pro_compatible::price_info::{PriceInfoObject as ProPriceInfoObject}; + use switchboard::aggregator::{Aggregator}; + + // Events + struct PriceRegulation has copy, drop { + level: u8, + config_address: address, + feed_address: address, + price_diff_threshold1: u64, + price_diff_threshold2: u64, + current_time: u64, + diff_threshold2_timer: u64, + max_duration_within_thresholds: u64, + primary_price: u256, + secondary_price: u256, + } + + struct InvalidOraclePrice has copy, drop { + config_address: address, + feed_address: address, + provider: String, + price: u256, + maximum_effective_price: u256, + minimum_effective_price: u256, + maximum_allowed_span: u64, + current_timestamp: u64, + historical_price_ttl: u64, + historical_price: u256, + historical_updated_time: u64, + } + + struct OracleUnavailable has copy, drop { + type: u8, + config_address: address, + feed_address: address, + provider: String, + price: u256, + updated_time: u64, + } + + // Deprecated: legacy Pyth deployment is retired after the Pyth Core upgrade (2026-07-31) + #[allow(unused_variable)] + native public fun update_single_price_v2(clock: &Clock, oracle_config: &mut OracleConfig, price_oracle: &mut PriceOracle, supra_oracle_holder: &OracleHolder, pyth_price_info: &PriceInfoObject, switchboard_aggregator: &Aggregator, feed_address: address); + native public fun update_single_price_v3(clock: &Clock, oracle_config: &mut OracleConfig, price_oracle: &mut PriceOracle, supra_oracle_holder: &OracleHolder, pyth_price_info: &ProPriceInfoObject, switchboard_aggregator: &Aggregator, feed_address: address); + + #[allow(unused_variable)] native public fun update_single_price(clock: &Clock, oracle_config: &mut OracleConfig, price_oracle: &mut PriceOracle, supra_oracle_holder: &OracleHolder, pyth_price_info: &PriceInfoObject, feed_address: address); + #[allow(unused_variable)] native public fun get_price_from_adaptor(oracle_provider_config: &OracleProviderConfig, target_decimal: u8, supra_oracle_holder: &OracleHolder, pyth_price_info: &PriceInfoObject): (u256, u64); -} \ No newline at end of file + + // Deprecated: legacy Pyth deployment is retired after the Pyth Core upgrade (2026-07-31) + #[allow(unused_variable)] + native public fun get_price_from_adaptor_v2(oracle_provider_config: &OracleProviderConfig, target_decimal: u8, supra_oracle_holder: &OracleHolder, pyth_price_info: &PriceInfoObject, switchboard_aggregator: &Aggregator): (u256, u64); + + native public fun get_price_from_adaptor_v3(oracle_provider_config: &OracleProviderConfig, target_decimal: u8, supra_oracle_holder: &OracleHolder, pyth_price_info: &ProPriceInfoObject, switchboard_aggregator: &Aggregator): (u256, u64); + +} diff --git a/oracle/sources/oracle_provider.move b/oracle/sources/oracle_provider.move index a2c0bc2..3c92e67 100644 --- a/oracle/sources/oracle_provider.move +++ b/oracle/sources/oracle_provider.move @@ -1,14 +1,13 @@ module oracle::oracle_provider { + use std::ascii::{String}; - #[allow(unused_field)] struct OracleProviderConfig has store { provider: OracleProvider, enable: bool, pair_id: vector, } - #[allow(unused_field)] struct OracleProvider has copy, store, drop { name: String } @@ -23,9 +22,12 @@ module oracle::oracle_provider { native public fun pyth_provider(): OracleProvider; + native public fun switchboard_provider(): OracleProvider; + native public fun new_empty_provider(): OracleProvider; native public fun to_string(f: &OracleProvider): String; native public fun is_empty(f: &OracleProvider): bool; -} \ No newline at end of file + +} diff --git a/oracle/sources/oracle_utils.move b/oracle/sources/oracle_utils.move index 15ddd41..29aee7f 100644 --- a/oracle/sources/oracle_utils.move +++ b/oracle/sources/oracle_utils.move @@ -1,4 +1,8 @@ module oracle::oracle_utils { + + // to_target_decimal_value: return value, using target decimal + // value = 10000000000, decimal = 9, target_decimal: 6 -> value = 10000000 + // production env: max target_decimal = 16, max value = max u128 => max return < max u256 native public fun to_target_decimal_value_safe(value: u256, decimal: u64, target_decimal: u64): u256; native public fun to_target_decimal_value(value: u256, decimal: u8, target_decimal: u8): u256; @@ -6,4 +10,5 @@ module oracle::oracle_utils { native public fun calculate_amplitude(a: u256, b: u256): u64; native public fun abs_sub(a: u256, b: u256): u256; -} \ No newline at end of file + +} diff --git a/oracle/sources/oracle_version.move b/oracle/sources/oracle_version.move index b79b782..13e7a9e 100644 --- a/oracle/sources/oracle_version.move +++ b/oracle/sources/oracle_version.move @@ -1,16 +1,9 @@ module oracle::oracle_version { - use oracle::oracle_error::{Self as error}; - use oracle::oracle_constants::{Self as constants}; - public fun this_version(): u64 { - constants::version() - } + native public fun this_version(): u64; - public fun next_version(): u64 { - constants::version() + 1 - } + native public fun next_version(): u64; - public fun pre_check_version(v: u64) { - assert!(v == constants::version(), error::incorrect_version()) - } -} \ No newline at end of file + native public fun pre_check_version(v: u64); + +} diff --git a/oracle/sources/strategy.move b/oracle/sources/strategy.move index 9b5046f..7d907b8 100644 --- a/oracle/sources/strategy.move +++ b/oracle/sources/strategy.move @@ -1,17 +1,14 @@ module oracle::strategy { + + // |------------------------------------------|------------------------------------------------------|-------------------------------------------------------------------| + // 0 x1 x2 n + // |is_within_diff1=true, is_within_diff2=true| is_within_diff1=false,is_within_diff2=true | is_within_diff1=false,is_within_diff2=false | + // returns return severity, critical/major/warning/normal etc. native public fun validate_price_difference(primary_price: u256, secondary_price: u256, threshold1: u64, threshold2: u64, current_timestamp: u64, max_duration_within_thresholds: u64, ratio2_usage_start_time: u64): u8; // return bool: is_normal - native public fun validate_price_range_and_history( - price: u256, - maximum_effective_price: u256, - minimum_effective_price: u256, - maximum_allowed_span_percentage: u64, - current_timestamp: u64, - historical_price_ttl: u64, - historical_price: u256, - historical_updated_time: u64, - ): bool; + native public fun validate_price_range_and_history(price: u256, maximum_effective_price: u256, minimum_effective_price: u256, maximum_allowed_span_percentage: u64, current_timestamp: u64, historical_price_ttl: u64, historical_price: u256, historical_updated_time: u64): bool; native public fun is_oracle_price_fresh(current_timestamp: u64, oracle_timestamp: u64, max_timestamp_diff: u64): bool; -} \ No newline at end of file + +} diff --git a/utils/Move.toml b/utils/Move.toml index 59298a5..ec6d1a4 100644 --- a/utils/Move.toml +++ b/utils/Move.toml @@ -1,7 +1,6 @@ [package] name = "utils" version = "0.0.1" -published-at = "0x66aa3335901ce7e04b85ed6597ee42d4b479f7110bf98e8ebd474fa32a0027e1" [dependencies.Sui] git = "https://github.com/MystenLabs/sui.git" @@ -10,4 +9,4 @@ rev = "mainnet" [addresses] sui = "0x2" -utils = "0x66aa3335901ce7e04b85ed6597ee42d4b479f7110bf98e8ebd474fa32a0027e1" +utils = "0x0"