log base reward after boost rewards

This commit is contained in:
alex
2024-10-08 00:41:18 -07:00
33 changed files with 508 additions and 1444 deletions

359
Cargo.lock generated
View File

@@ -58,7 +58,7 @@ dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy 0.7.35",
"zerocopy",
]
[[package]]
@@ -72,9 +72,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.86"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "ark-bn254"
@@ -201,15 +201,15 @@ checksum = "8bcb85e548c05d407fa6faff46b750ba287714ef32afc0f5e15b4641ffd6affb"
[[package]]
name = "arrayref"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.4"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "assert_matches"
@@ -230,9 +230,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
@@ -246,12 +246,6 @@ version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bincode"
version = "1.3.3"
@@ -345,11 +339,11 @@ dependencies = [
[[package]]
name = "borsh"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee"
dependencies = [
"borsh-derive 0.10.3",
"borsh-derive 0.10.4",
"hashbrown 0.13.2",
]
@@ -378,12 +372,12 @@ dependencies = [
[[package]]
name = "borsh-derive"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7"
checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89"
dependencies = [
"borsh-derive-internal 0.10.3",
"borsh-schema-derive-internal 0.10.3",
"borsh-derive-internal 0.10.4",
"borsh-schema-derive-internal 0.10.4",
"proc-macro-crate 0.1.5",
"proc-macro2",
"syn 1.0.109",
@@ -396,10 +390,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b"
dependencies = [
"once_cell",
"proc-macro-crate 3.1.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
"syn_derive",
]
@@ -416,9 +410,9 @@ dependencies = [
[[package]]
name = "borsh-derive-internal"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb"
checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3"
dependencies = [
"proc-macro2",
"quote",
@@ -438,9 +432,9 @@ dependencies = [
[[package]]
name = "borsh-schema-derive-internal"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd"
checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4"
dependencies = [
"proc-macro2",
"quote",
@@ -471,22 +465,22 @@ dependencies = [
[[package]]
name = "bytemuck"
version = "1.16.3"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83"
checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
version = "1.7.0"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b"
checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -497,12 +491,13 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.1.7"
version = "1.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1"
dependencies = [
"jobserver",
"libc",
"shlex",
]
[[package]]
@@ -567,15 +562,15 @@ dependencies = [
[[package]]
name = "constant_time_eq"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
[[package]]
name = "cpufeatures"
version = "0.2.12"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
@@ -675,7 +670,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -686,7 +681,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -728,9 +723,9 @@ dependencies = [
[[package]]
name = "drillx"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c5fd3a8f11a6420d6efb1952c8c2e788627cb2c9e834537dc4b6bd036461646"
checksum = "9f1b6097a8aeb360dc83cad60047b42cfabf54a56b81a75e254f5854211a7475"
dependencies = [
"equix",
"serde",
@@ -828,9 +823,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "equix"
version = "0.1.5"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced5aa2974d730a3bbe65dcb62ad8fbb0ae44d4aeed1093808a855d922b931ee"
checksum = "b3e45c3367b4177f7b3512daf285f19cb3f0eed6d4c1e5d9bc37e4c1026c5644"
dependencies = [
"arrayvec",
"hashx",
@@ -914,9 +909,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.14.5"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
name = "hashx"
@@ -1014,12 +1009,12 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.3.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown 0.14.5",
"hashbrown 0.15.0",
]
[[package]]
@@ -1048,9 +1043,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.69"
version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
dependencies = [
"wasm-bindgen",
]
@@ -1078,9 +1073,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.155"
version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "libsecp256k1"
@@ -1200,7 +1195,7 @@ version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf0f61b553e424a6234af1268456972ee66c2222e1da89079242251fa7479e5"
dependencies = [
"borsh 0.10.3",
"borsh 0.10.4",
"num-derive 0.3.3",
"num-traits",
"solana-program",
@@ -1236,7 +1231,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -1272,17 +1267,17 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
"proc-macro-crate 3.1.0",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
name = "once_cell"
version = "1.19.0"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "opaque-debug"
@@ -1300,11 +1295,11 @@ dependencies = [
"drillx",
"mpl-token-metadata",
"num_enum",
"ore-utils",
"solana-program",
"spl-associated-token-account",
"spl-token",
"static_assertions",
"steel",
"thiserror",
]
@@ -1316,11 +1311,11 @@ dependencies = [
"bytemuck",
"const-crypto",
"num_enum",
"ore-utils",
"solana-program",
"spl-associated-token-account",
"spl-token",
"static_assertions",
"steel",
"thiserror",
]
@@ -1328,26 +1323,15 @@ dependencies = [
name = "ore-program"
version = "2.1.9"
dependencies = [
"base64 0.22.1",
"drillx",
"mpl-token-metadata",
"ore-api",
"ore-boost-api",
"ore-utils",
"rand 0.8.5",
"solana-program",
"spl-associated-token-account",
"spl-token",
]
[[package]]
name = "ore-utils"
version = "2.1.9"
dependencies = [
"bytemuck",
"solana-program",
"spl-associated-token-account",
"spl-token",
"steel",
]
[[package]]
@@ -1417,11 +1401,11 @@ dependencies = [
[[package]]
name = "ppv-lite86"
version = "0.2.18"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy 0.6.6",
"zerocopy",
]
[[package]]
@@ -1435,9 +1419,9 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit",
]
@@ -1468,9 +1452,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.86"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
dependencies = [
"unicode-ident",
]
@@ -1492,14 +1476,14 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
name = "quote"
version = "1.0.36"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
@@ -1606,18 +1590,18 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.3"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "regex"
version = "1.10.5"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
@@ -1627,9 +1611,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.7"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
@@ -1638,9 +1622,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc-hash"
@@ -1650,9 +1634,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
@@ -1683,9 +1667,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.204"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
@@ -1701,20 +1685,20 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.204"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
name = "serde_json"
version = "1.0.121"
version = "1.0.128"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609"
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
dependencies = [
"itoa",
"memchr",
@@ -1741,7 +1725,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -1796,6 +1780,12 @@ dependencies = [
"keccak",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signature"
version = "1.6.4"
@@ -1826,9 +1816,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "solana-frozen-abi"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f0c52f25d28a1b5af57d5de3802e49883f68792a343101a9daf9817d8dfffff"
checksum = "45478bad85abd8cc291775463e15bc1031fdbf973d48e2568e8defee3d842a3a"
dependencies = [
"block-buffer 0.10.4",
"bs58",
@@ -1851,21 +1841,21 @@ dependencies = [
[[package]]
name = "solana-frozen-abi-macro"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7d0abca44a21c83305e8650341f67ccc919a1a9dd698ddafc86e78b74b9296"
checksum = "c5cb05f9051446226cd26ea17f6fbe5e28e922ad6a846166db7fb17865090fcb"
dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
name = "solana-logger"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5bc0644a410b8bff84ad18541a176f27776062b1ad116cb315c6f5f14b94fed"
checksum = "4cbcde62a32962c3f80aebe0047476dcb2b693b5d47110071af0d23561c3aa0c"
dependencies = [
"env_logger",
"lazy_static",
@@ -1874,9 +1864,9 @@ dependencies = [
[[package]]
name = "solana-program"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a99c3bc26fda40f42db98494271bda4906b0d7ab55f3ea7755fa5f110f58b5"
checksum = "a52f4c424433a18b57ae88a35b677c548879a9c4ca1e27e108d1597ff12b95ac"
dependencies = [
"ark-bn254",
"ark-ec",
@@ -1886,7 +1876,7 @@ dependencies = [
"bincode",
"bitflags 2.6.0",
"blake3",
"borsh 0.10.3",
"borsh 0.10.4",
"borsh 0.9.3",
"borsh 1.5.1",
"bs58",
@@ -1929,9 +1919,9 @@ dependencies = [
[[package]]
name = "solana-sdk"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90a8affb5b3acd43f7164368b88243bf091e46eccff9bea5b743e4691d7c2600"
checksum = "02bfb6b467e755620f4d3f8eefd1e5bdfb812ec7076d237e0280d7c988f16f02"
dependencies = [
"assert_matches",
"base64 0.21.7",
@@ -1984,15 +1974,15 @@ dependencies = [
[[package]]
name = "solana-sdk-macro"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2ac8d7ef471476164edb2ed105bcf26071835a15f0e74703929d4ec913676b"
checksum = "9ed90de8086a0e114ab63454a9d066e0f08eb2c9c8aea149ff60e8a492f165fc"
dependencies = [
"bs58",
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2003,9 +1993,9 @@ checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183"
[[package]]
name = "solana-zk-token-sdk"
version = "1.18.20"
version = "1.18.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf73fd7e430bf3269539c2fb1d05af0df26fc3b7bc090172ceda5cd4340657c"
checksum = "7569e85e3b1c8abc089ec06153b4ded577bc94bf383f607d5017082497f53665"
dependencies = [
"aes-gcm-siv",
"base64 0.21.7",
@@ -2037,7 +2027,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "992d9c64c2564cc8f63a4b508bf3ebcdf2254b0429b13cd1d31adb6162432a5f"
dependencies = [
"assert_matches",
"borsh 0.10.3",
"borsh 0.10.4",
"num-derive 0.4.2",
"num-traits",
"solana-program",
@@ -2065,7 +2055,7 @@ checksum = "07fd7858fc4ff8fb0e34090e41d7eb06a823e1057945c26d480bfc21d2338a93"
dependencies = [
"quote",
"spl-discriminator-syn",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2077,7 +2067,7 @@ dependencies = [
"proc-macro2",
"quote",
"sha2 0.10.8",
"syn 2.0.72",
"syn 2.0.79",
"thiserror",
]
@@ -2096,7 +2086,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2881dddfca792737c0706fa0175345ab282b1b0879c7d877bad129645737c079"
dependencies = [
"borsh 0.10.3",
"borsh 0.10.4",
"bytemuck",
"solana-program",
"solana-zk-token-sdk",
@@ -2125,7 +2115,7 @@ dependencies = [
"proc-macro2",
"quote",
"sha2 0.10.8",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2200,7 +2190,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f"
dependencies = [
"borsh 0.10.3",
"borsh 0.10.4",
"solana-program",
"spl-discriminator",
"spl-pod",
@@ -2243,6 +2233,20 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "steel"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d88c610ca9fd5e4e51bdb6e9964114133a42f006713fe38aff37266fac91e1be"
dependencies = [
"bytemuck",
"num_enum",
"solana-program",
"spl-associated-token-account",
"spl-token",
"thiserror",
]
[[package]]
name = "strsim"
version = "0.11.1"
@@ -2268,7 +2272,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2290,9 +2294,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.72"
version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [
"proc-macro2",
"quote",
@@ -2308,7 +2312,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2322,22 +2326,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.63"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2391,9 +2395,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
[[package]]
name = "toml_edit"
version = "0.21.1"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap",
"toml_datetime",
@@ -2408,15 +2412,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
dependencies = [
"tinyvec",
]
@@ -2449,13 +2453,13 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "visibility"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3fd98999db9227cf28e59d83e1f120f42bc233d4b152e8fab9bc87d5bb1e0f8"
checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2472,34 +2476,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2507,28 +2512,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
[[package]]
name = "web-sys"
version = "0.3.69"
version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2552,9 +2557,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys",
]
@@ -2567,9 +2572,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
@@ -2640,41 +2645,21 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.5.40"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"memchr",
]
[[package]]
name = "zerocopy"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
dependencies = [
"byteorder",
"zerocopy-derive 0.6.6",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive 0.7.35",
]
[[package]]
name = "zerocopy-derive"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"byteorder",
"zerocopy-derive",
]
[[package]]
@@ -2685,7 +2670,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]
[[package]]
@@ -2705,5 +2690,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"syn 2.0.79",
]

View File

@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["api", "program", "utils"]
members = ["api", "program"]
[workspace.package]
version = "2.1.9"
@@ -21,11 +21,9 @@ mpl-token-metadata = "4.1.2"
num_enum = "0.7.2"
ore-api = { path = "api", version = "2.1.9" }
ore-boost-api = { path = "../ore-boost/api", version = "0.1.0" }
ore-utils = { path = "utils", features = ["spl"], version = "2.1.9" }
solana-program = "^1.18"
spl-token = { version = "^4", features = ["no-entrypoint"] }
spl-associated-token-account = { version = "^2.3", features = [ "no-entrypoint" ] }
static_assertions = "1.1.0"
steel = { features = ["spl"], version = "1.0" }
thiserror = "1.0.57"

View File

@@ -16,9 +16,9 @@ const-crypto.workspace = true
drillx.workspace = true
mpl-token-metadata.workspace = true
num_enum.workspace = true
ore-utils.workspace = true
solana-program.workspace = true
spl-token.workspace = true
spl-associated-token-account.workspace = true
static_assertions.workspace = true
steel.workspace = true
thiserror.workspace = true

View File

@@ -1,6 +1,4 @@
use num_enum::IntoPrimitive;
use ore_utils::*;
use thiserror::Error;
use steel::*;
#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)]
#[repr(u32)]

View File

@@ -1,6 +1,4 @@
use bytemuck::{Pod, Zeroable};
use ore_utils::*;
use solana_program::pubkey::Pubkey;
use steel::*;
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
@@ -16,5 +14,6 @@ pub struct BoostEvent {
pub mint: Pubkey,
pub reward: u64,
}
event!(MineEvent);
event!(BoostEvent);

View File

@@ -1,6 +1,4 @@
use bytemuck::{Pod, Zeroable};
use num_enum::TryFromPrimitive;
use ore_utils::*;
use steel::*;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]

View File

@@ -6,6 +6,16 @@ pub mod loaders;
pub mod sdk;
pub mod state;
use solana_program::declare_id;
pub mod prelude {
pub use crate::consts::*;
pub use crate::error::*;
pub use crate::event::*;
pub use crate::instruction::*;
pub use crate::loaders::*;
pub use crate::sdk::*;
pub use crate::state::*;
}
use steel::*;
declare_id!("7dNmnKiRRazHV9c6qzy39iJMLobSAx487XvD3C1hVgvt");

View File

@@ -1,234 +1,28 @@
use ore_utils::*;
use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey};
use steel::*;
use crate::{
consts::*,
state::{Bus, Config, Proof, Treasury},
state::{Config, Treasury},
};
/// Errors if:
/// - Owner is not Ore program.
/// - Address does not match the expected bus address.
/// - Data is empty.
/// - Data cannot deserialize into a bus account.
/// - Bus ID does not match the expected ID.
/// - Expected to be writable, but is not.
pub fn load_bus(info: &AccountInfo<'_>, id: u64, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.key.ne(&BUS_ADDRESSES[id as usize]) {
return Err(ProgramError::InvalidSeeds);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
let bus_data = info.data.borrow();
let bus = Bus::try_from_bytes(&bus_data)?;
if bus.id.ne(&id) {
return Err(ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
pub trait OreAccountInfoValidation {
fn is_config(&self) -> Result<&Self, ProgramError>;
fn is_treasury(&self) -> Result<&Self, ProgramError>;
fn is_treasury_tokens(&self) -> Result<&Self, ProgramError>;
}
/// Errors if:
/// - Owner is not Ore program.
/// - Data is empty.
/// - Data cannot deserialize into a bus account.
/// - Bus ID is not in the expected range.
/// - Address is not in set of valid bus address.
/// - Expected to be writable, but is not.
pub fn load_any_bus(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
impl OreAccountInfoValidation for AccountInfo<'_> {
fn is_config(&self) -> Result<&Self, ProgramError> {
self.has_address(&CONFIG_ADDRESS)?
.is_type::<Config>(&crate::ID)
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
fn is_treasury(&self) -> Result<&Self, ProgramError> {
self.has_address(&TREASURY_ADDRESS)?
.is_type::<Treasury>(&crate::ID)
}
if info.data.borrow()[0].ne(&(Bus::discriminator() as u8)) {
return Err(solana_program::program_error::ProgramError::InvalidAccountData);
fn is_treasury_tokens(&self) -> Result<&Self, ProgramError> {
self.has_address(&TREASURY_TOKENS_ADDRESS)
}
if !BUS_ADDRESSES.contains(info.key) {
return Err(ProgramError::InvalidSeeds);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not Ore program.
/// - Address does not match the expected address.
/// - Data is empty.
/// - Data cannot deserialize into a config account.
/// - Expected to be writable, but is not.
pub fn load_config(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.key.ne(&CONFIG_ADDRESS) {
return Err(ProgramError::InvalidSeeds);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
if info.data.borrow()[0].ne(&(Config::discriminator() as u8)) {
return Err(solana_program::program_error::ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not Ore program.
/// - Data is empty.
/// - Data cannot deserialize into a proof account.
/// - Proof authority does not match the expected address.
/// - Expected to be writable, but is not.
pub fn load_proof(
info: &AccountInfo<'_>,
authority: &Pubkey,
is_writable: bool,
) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
let proof_data = info.data.borrow();
let proof = Proof::try_from_bytes(&proof_data)?;
if proof.authority.ne(&authority) {
return Err(ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not Ore program.
/// - Data is empty.
/// - Data cannot deserialize into a proof account.
/// - Proof miner does not match the expected address.
/// - Expected to be writable, but is not.
pub fn load_proof_with_miner(
info: &AccountInfo<'_>,
miner: &Pubkey,
is_writable: bool,
) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
let proof_data = info.data.borrow();
let proof = Proof::try_from_bytes(&proof_data)?;
if proof.miner.ne(&miner) {
return Err(ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not Ore program.
/// - Data is empty.
/// - Data cannot deserialize into a proof account.
/// - Expected to be writable, but is not.
pub fn load_any_proof(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
if info.data.borrow()[0].ne(&(Proof::discriminator() as u8)) {
return Err(solana_program::program_error::ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not Ore program.
/// - Address does not match the expected address.
/// - Data is empty.
/// - Data cannot deserialize into a treasury account.
/// - Expected to be writable, but is not.
pub fn load_treasury(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&crate::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.key.ne(&TREASURY_ADDRESS) {
return Err(ProgramError::InvalidSeeds);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
if info.data.borrow()[0].ne(&(Treasury::discriminator() as u8)) {
return Err(solana_program::program_error::ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Address does not match the expected treasury tokens address.
/// - Cannot load as a token account
pub fn load_treasury_tokens(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.key.ne(&TREASURY_TOKENS_ADDRESS) {
return Err(ProgramError::InvalidSeeds);
}
load_token_account(info, Some(&TREASURY_ADDRESS), &MINT_ADDRESS, is_writable)
}

View File

@@ -1,9 +1,5 @@
use drillx::Solution;
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program, sysvar,
};
use steel::*;
use crate::{
consts::*,
@@ -23,19 +19,15 @@ pub fn auth(proof: Pubkey) -> Instruction {
/// Builds a claim instruction.
pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
let proof = proof_pda(signer).0;
let treasury_tokens = spl_associated_token_account::get_associated_token_address(
&TREASURY_ADDRESS,
&MINT_ADDRESS,
);
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(beneficiary, false),
AccountMeta::new(proof, false),
AccountMeta::new_readonly(TREASURY_ADDRESS, false),
AccountMeta::new(treasury_tokens, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new(TREASURY_TOKENS_ADDRESS, false),
AccountMeta::new_readonly(spl_token::ID, false),
],
data: Claim {
amount: amount.to_le_bytes(),
@@ -48,11 +40,11 @@ pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
pub fn close(signer: Pubkey) -> Instruction {
let proof = proof_pda(signer).0;
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(proof, false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(solana_program::system_program::ID, false),
],
data: Close {}.to_bytes(),
}
@@ -67,22 +59,21 @@ pub fn mine(
boost_accounts: Vec<Pubkey>,
) -> Instruction {
let proof = proof_pda(authority).0;
let accounts = vec![
let required_accounts = vec![
AccountMeta::new(signer, true),
AccountMeta::new(bus, false),
AccountMeta::new_readonly(CONFIG_ADDRESS, false),
AccountMeta::new(proof, false),
AccountMeta::new_readonly(sysvar::instructions::id(), false),
AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
AccountMeta::new_readonly(sysvar::instructions::ID, false),
AccountMeta::new_readonly(sysvar::slot_hashes::ID, false),
];
let boost_accounts = boost_accounts
let optional_accounts = boost_accounts
.into_iter()
.map(|pk| AccountMeta::new_readonly(pk, false))
.collect();
let accounts = [accounts, boost_accounts].concat();
Instruction {
program_id: crate::id(),
accounts,
program_id: crate::ID,
accounts: [required_accounts, optional_accounts].concat(),
data: Mine {
digest: solution.d,
nonce: solution.n,
@@ -95,14 +86,14 @@ pub fn mine(
pub fn open(signer: Pubkey, miner: Pubkey, payer: Pubkey) -> Instruction {
let proof_pda = proof_pda(signer);
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new_readonly(miner, false),
AccountMeta::new(payer, true),
AccountMeta::new(proof_pda.0, false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
AccountMeta::new_readonly(solana_program::system_program::ID, false),
AccountMeta::new_readonly(sysvar::slot_hashes::ID, false),
],
data: Open { bump: proof_pda.1 }.to_bytes(),
}
@@ -110,12 +101,8 @@ pub fn open(signer: Pubkey, miner: Pubkey, payer: Pubkey) -> Instruction {
/// Builds a reset instruction.
pub fn reset(signer: Pubkey) -> Instruction {
let treasury_tokens = spl_associated_token_account::get_associated_token_address(
&TREASURY_ADDRESS,
&MINT_ADDRESS,
);
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(BUS_ADDRESSES[0], false),
@@ -129,8 +116,8 @@ pub fn reset(signer: Pubkey) -> Instruction {
AccountMeta::new(CONFIG_ADDRESS, false),
AccountMeta::new(MINT_ADDRESS, false),
AccountMeta::new(TREASURY_ADDRESS, false),
AccountMeta::new(treasury_tokens, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new(TREASURY_TOKENS_ADDRESS, false),
AccountMeta::new_readonly(spl_token::ID, false),
],
data: Reset {}.to_bytes(),
}
@@ -139,18 +126,14 @@ pub fn reset(signer: Pubkey) -> Instruction {
/// Build a stake instruction.
pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
let proof = proof_pda(signer).0;
let treasury_tokens = spl_associated_token_account::get_associated_token_address(
&TREASURY_ADDRESS,
&MINT_ADDRESS,
);
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(proof, false),
AccountMeta::new(sender, false),
AccountMeta::new(treasury_tokens, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new(TREASURY_TOKENS_ADDRESS, false),
AccountMeta::new_readonly(spl_token::ID, false),
],
data: Stake {
amount: amount.to_le_bytes(),
@@ -163,7 +146,7 @@ pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
pub fn update(signer: Pubkey, miner: Pubkey) -> Instruction {
let proof = proof_pda(signer).0;
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new_readonly(miner, false),
@@ -176,7 +159,7 @@ pub fn update(signer: Pubkey, miner: Pubkey) -> Instruction {
// Build an upgrade instruction.
pub fn upgrade(signer: Pubkey, beneficiary: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(beneficiary, false),
@@ -184,7 +167,7 @@ pub fn upgrade(signer: Pubkey, beneficiary: Pubkey, sender: Pubkey, amount: u64)
AccountMeta::new(MINT_V1_ADDRESS, false),
AccountMeta::new(sender, false),
AccountMeta::new(TREASURY_ADDRESS, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(spl_token::ID, false),
],
data: Upgrade {
amount: amount.to_le_bytes(),
@@ -206,10 +189,8 @@ pub fn initialize(signer: Pubkey) -> Instruction {
bus_pda(7),
];
let config_pda = config_pda();
let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &crate::id());
let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &crate::ID);
let treasury_pda = treasury_pda();
let treasury_tokens =
spl_associated_token_account::get_associated_token_address(&treasury_pda.0, &mint_pda.0);
let metadata_pda = Pubkey::find_program_address(
&[
METADATA,
@@ -219,7 +200,7 @@ pub fn initialize(signer: Pubkey) -> Instruction {
&mpl_token_metadata::ID,
);
Instruction {
program_id: crate::id(),
program_id: crate::ID,
accounts: vec![
AccountMeta::new(signer, true),
AccountMeta::new(bus_pdas[0].0, false),
@@ -234,12 +215,12 @@ pub fn initialize(signer: Pubkey) -> Instruction {
AccountMeta::new(metadata_pda.0, false),
AccountMeta::new(mint_pda.0, false),
AccountMeta::new(treasury_pda.0, false),
AccountMeta::new(treasury_tokens, false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(spl_associated_token_account::id(), false),
AccountMeta::new(TREASURY_TOKENS_ADDRESS, false),
AccountMeta::new_readonly(system_program::ID, false),
AccountMeta::new_readonly(spl_token::ID, false),
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
AccountMeta::new_readonly(mpl_token_metadata::ID, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::rent::ID, false),
],
data: Initialize {
bus_0_bump: bus_pdas[0].1,

View File

@@ -1,8 +1,4 @@
use bytemuck::{Pod, Zeroable};
use ore_utils::*;
use solana_program::pubkey::Pubkey;
use crate::consts::BUS;
use steel::*;
use super::OreAccount;
@@ -25,9 +21,4 @@ pub struct Bus {
pub top_balance: u64,
}
/// Fetch the PDA of a bus account.
pub fn bus_pda(id: u8) -> (Pubkey, u8) {
Pubkey::find_program_address(&[BUS, &[id]], &crate::id())
}
account!(OreAccount, Bus);

View File

@@ -1,8 +1,4 @@
use bytemuck::{Pod, Zeroable};
use ore_utils::*;
use solana_program::pubkey::Pubkey;
use crate::consts::CONFIG;
use steel::*;
use super::OreAccount;
@@ -23,9 +19,4 @@ pub struct Config {
pub top_balance: u64,
}
/// Derive the PDA of the config account.
pub fn config_pda() -> (Pubkey, u8) {
Pubkey::find_program_address(&[CONFIG], &crate::id())
}
account!(OreAccount, Config);

View File

@@ -8,7 +8,9 @@ pub use config::*;
pub use proof::*;
pub use treasury::*;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use steel::*;
use crate::consts::*;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
@@ -18,3 +20,23 @@ pub enum OreAccount {
Proof = 102,
Treasury = 103,
}
/// Fetch the PDA of a bus account.
pub fn bus_pda(id: u8) -> (Pubkey, u8) {
Pubkey::find_program_address(&[BUS, &[id]], &crate::id())
}
/// Derive the PDA of the config account.
pub fn config_pda() -> (Pubkey, u8) {
Pubkey::find_program_address(&[CONFIG], &crate::id())
}
/// Derive the PDA of a proof account.
pub fn proof_pda(authority: Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[PROOF, authority.as_ref()], &crate::id())
}
/// Derive the PDA of the treasury account.
pub fn treasury_pda() -> (Pubkey, u8) {
Pubkey::find_program_address(&[TREASURY], &crate::id())
}

View File

@@ -1,8 +1,4 @@
use bytemuck::{Pod, Zeroable};
use ore_utils::*;
use solana_program::pubkey::Pubkey;
use crate::consts::PROOF;
use steel::*;
use super::OreAccount;
@@ -39,9 +35,4 @@ pub struct Proof {
pub total_rewards: u64,
}
/// Derive the PDA of a proof account.
pub fn proof_pda(authority: Pubkey) -> (Pubkey, u8) {
Pubkey::find_program_address(&[PROOF, authority.as_ref()], &crate::id())
}
account!(OreAccount, Proof);

View File

@@ -1,8 +1,4 @@
use bytemuck::{Pod, Zeroable};
use ore_utils::*;
use solana_program::pubkey::Pubkey;
use crate::consts::TREASURY;
use steel::*;
use super::OreAccount;
@@ -12,9 +8,4 @@ use super::OreAccount;
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
pub struct Treasury {}
/// Derive the PDA of the treasury account.
pub fn treasury_pda() -> (Pubkey, u8) {
Pubkey::find_program_address(&[TREASURY], &crate::id())
}
account!(OreAccount, Treasury);

View File

@@ -22,11 +22,10 @@ drillx.workspace = true
mpl-token-metadata.workspace = true
ore-api.workspace = true
ore-boost-api.workspace = true
ore-utils.workspace = true
solana-program.workspace = true
spl-token.workspace = true
spl-associated-token-account.workspace = true
base64 = "0.22.1"
steel.workspace = true
[dev-dependencies]
rand = "0.8.5"

View File

@@ -1,8 +1,5 @@
use ore_api::{consts::*, error::OreError, instruction::*, loaders::*, state::Proof};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
};
use ore_api::prelude::*;
use steel::*;
/// Claim distributes claimable ORE from the treasury to a miner.
pub fn process_claim(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
@@ -11,21 +8,24 @@ pub fn process_claim(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
let amount = u64::from_le_bytes(args.amount);
// Load accounts.
let [signer, beneficiary_info, proof_info, treasury_info, treasury_tokens_info, token_program] =
let [signer_info, beneficiary_info, proof_info, treasury_info, treasury_tokens_info, token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_token_account(beneficiary_info, None, &MINT_ADDRESS, true)?;
load_proof(proof_info, signer.key, true)?;
load_treasury(treasury_info, false)?;
load_treasury_tokens(treasury_tokens_info, true)?;
load_program(token_program, spl_token::id())?;
signer_info.is_signer()?;
beneficiary_info
.is_writable()?
.to_token_account()?
.check(|t| t.mint == MINT_ADDRESS)?;
let proof = proof_info
.to_account_mut::<Proof>(&ore_api::ID)?
.check_mut(|p| p.authority == *signer_info.key)?;
treasury_info.is_treasury()?;
treasury_tokens_info.is_writable()?.is_treasury_tokens()?;
token_program.is_program(&spl_token::ID)?;
// Update miner balance.
let mut proof_data = proof_info.data.borrow_mut();
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
proof.balance = proof
.balance
.checked_sub(amount)

View File

@@ -1,33 +1,25 @@
use ore_api::{loaders::*, state::Proof};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
system_program,
};
use ore_api::prelude::*;
use steel::*;
/// Close closes a proof account and returns the rent to the owner.
pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
// Load accounts.
let [signer, proof_info, system_program] = accounts else {
let [signer_info, proof_info, system_program] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_proof(proof_info, signer.key, true)?;
load_program(system_program, system_program::id())?;
// Validate balance is zero.
let proof_data = proof_info.data.borrow();
let proof = Proof::try_from_bytes(&proof_data)?;
if proof.balance.gt(&0) {
return Err(ProgramError::InvalidAccountData);
}
drop(proof_data);
signer_info.is_signer()?;
proof_info
.is_writable()?
.to_account::<Proof>(&ore_api::ID)?
.check(|p| p.authority == *signer_info.key)?
.check(|p| p.balance == 0)?;
system_program.is_program(&system_program::ID)?;
// Realloc data to zero.
proof_info.realloc(0, true)?;
// Send remaining lamports to signer.
**signer.lamports.borrow_mut() += proof_info.lamports();
**signer_info.lamports.borrow_mut() += proof_info.lamports();
**proof_info.lamports.borrow_mut() = 0;
Ok(())

View File

@@ -1,16 +1,7 @@
use std::mem::size_of;
use ore_api::{
consts::*,
instruction::*,
state::{Bus, Config, Treasury},
};
use ore_utils::*;
use solana_program::{
self, account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
program_pack::Pack, system_program, sysvar,
};
use ore_api::prelude::*;
use solana_program::program_pack::Pack;
use spl_token::state::Mint;
use steel::*;
/// Initialize sets up the ORE program to begin mining.
pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
@@ -18,23 +9,49 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramR
let args = Initialize::try_from_bytes(data)?;
// Load accounts.
let [signer, bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, bus_7_info, config_info, metadata_info, mint_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program, metadata_program, rent_sysvar] =
let [signer_info, bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, bus_7_info, config_info, metadata_info, mint_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program, metadata_program, rent_sysvar] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_uninitialized_pda(bus_0_info, &[BUS, &[0]], args.bus_0_bump, &ore_api::id())?;
load_uninitialized_pda(bus_1_info, &[BUS, &[1]], args.bus_1_bump, &ore_api::id())?;
load_uninitialized_pda(bus_2_info, &[BUS, &[2]], args.bus_2_bump, &ore_api::id())?;
load_uninitialized_pda(bus_3_info, &[BUS, &[3]], args.bus_3_bump, &ore_api::id())?;
load_uninitialized_pda(bus_4_info, &[BUS, &[4]], args.bus_4_bump, &ore_api::id())?;
load_uninitialized_pda(bus_5_info, &[BUS, &[5]], args.bus_5_bump, &ore_api::id())?;
load_uninitialized_pda(bus_6_info, &[BUS, &[6]], args.bus_6_bump, &ore_api::id())?;
load_uninitialized_pda(bus_7_info, &[BUS, &[7]], args.bus_7_bump, &ore_api::id())?;
load_uninitialized_pda(config_info, &[CONFIG], args.config_bump, &ore_api::id())?;
load_uninitialized_pda(
metadata_info,
signer_info.is_signer()?.has_address(&INITIALIZER_ADDRESS)?;
bus_0_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[0]], args.bus_0_bump, &ore_api::ID)?;
bus_1_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[1]], args.bus_1_bump, &ore_api::ID)?;
bus_2_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[2]], args.bus_2_bump, &ore_api::ID)?;
bus_3_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[3]], args.bus_3_bump, &ore_api::ID)?;
bus_4_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[4]], args.bus_4_bump, &ore_api::ID)?;
bus_5_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[5]], args.bus_5_bump, &ore_api::ID)?;
bus_6_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[6]], args.bus_6_bump, &ore_api::ID)?;
bus_7_info
.is_empty()?
.is_writable()?
.has_seeds(&[BUS, &[7]], args.bus_7_bump, &ore_api::ID)?;
config_info
.is_empty()?
.is_writable()?
.has_seeds(&[CONFIG], args.config_bump, &ore_api::ID)?;
metadata_info.is_empty()?.is_writable()?.has_seeds(
&[
METADATA,
mpl_token_metadata::ID.as_ref(),
@@ -43,29 +60,22 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramR
args.metadata_bump,
&mpl_token_metadata::ID,
)?;
load_uninitialized_pda(
mint_info,
mint_info.is_empty()?.is_writable()?.has_seeds(
&[MINT, MINT_NOISE.as_slice()],
args.mint_bump,
&ore_api::id(),
&ore_api::ID,
)?;
load_uninitialized_pda(
treasury_info,
treasury_info.is_empty()?.is_writable()?.has_seeds(
&[TREASURY],
args.treasury_bump,
&ore_api::id(),
&ore_api::ID,
)?;
load_system_account(treasury_tokens_info, true)?;
load_program(system_program, system_program::id())?;
load_program(token_program, spl_token::id())?;
load_program(associated_token_program, spl_associated_token_account::id())?;
load_program(metadata_program, mpl_token_metadata::ID)?;
load_sysvar(rent_sysvar, sysvar::rent::id())?;
// Check signer.
if signer.key.ne(&INITIALIZER_ADDRESS) {
return Err(ProgramError::MissingRequiredSignature);
}
treasury_tokens_info.is_empty()?.is_writable()?;
system_program.is_program(&system_program::ID)?;
token_program.is_program(&spl_token::ID)?;
associated_token_program.is_program(&spl_associated_token_account::ID)?;
metadata_program.is_program(&mpl_token_metadata::ID)?;
rent_sysvar.is_sysvar(&sysvar::rent::ID)?;
// Initialize bus accounts.
let bus_infos = [
@@ -83,17 +93,14 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramR
args.bus_7_bump,
];
for i in 0..BUS_COUNT {
create_pda(
create_account::<Bus>(
bus_infos[i],
&ore_api::id(),
8 + size_of::<Bus>(),
&ore_api::ID,
&[BUS, &[i as u8], &[bus_bumps[i]]],
system_program,
signer,
signer_info,
)?;
let mut bus_data = bus_infos[i].try_borrow_mut_data()?;
bus_data[0] = Bus::discriminator() as u8;
let bus = Bus::try_from_bytes_mut(&mut bus_data)?;
let bus = bus_infos[i].to_account_mut::<Bus>(&ore_api::ID)?;
bus.id = i as u64;
bus.rewards = 0;
bus.theoretical_rewards = 0;
@@ -101,47 +108,40 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramR
}
// Initialize config.
create_pda(
create_account::<Config>(
config_info,
&ore_api::id(),
8 + size_of::<Config>(),
&ore_api::ID,
&[CONFIG, &[args.config_bump]],
system_program,
signer,
signer_info,
)?;
let mut config_data = config_info.data.borrow_mut();
config_data[0] = Config::discriminator() as u8;
let config = Config::try_from_bytes_mut(&mut config_data)?;
let config = config_info.to_account_mut::<Config>(&ore_api::ID)?;
config.base_reward_rate = INITIAL_BASE_REWARD_RATE;
config.last_reset_at = 0;
config.min_difficulty = INITIAL_MIN_DIFFICULTY as u64;
config.top_balance = 0;
// Initialize treasury.
create_pda(
create_account::<Treasury>(
treasury_info,
&ore_api::id(),
8 + size_of::<Treasury>(),
&ore_api::ID,
&[TREASURY, &[args.treasury_bump]],
system_program,
signer,
signer_info,
)?;
let mut treasury_data = treasury_info.data.borrow_mut();
treasury_data[0] = Treasury::discriminator() as u8;
drop(treasury_data);
// Initialize mint.
create_pda(
allocate_account(
mint_info,
&spl_token::id(),
&spl_token::ID,
Mint::LEN,
&[MINT, MINT_NOISE.as_slice(), &[args.mint_bump]],
system_program,
signer,
signer_info,
)?;
solana_program::program::invoke_signed(
&spl_token::instruction::initialize_mint(
&spl_token::id(),
&spl_token::ID,
mint_info.key,
treasury_info.key,
None,
@@ -162,8 +162,8 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramR
metadata: metadata_info,
mint: mint_info,
mint_authority: treasury_info,
payer: signer,
update_authority: (signer, true),
payer: signer_info,
update_authority: (signer_info, true),
system_program,
rent: Some(rent_sysvar),
__args: mpl_token_metadata::instructions::CreateMetadataAccountV3InstructionArgs {
@@ -183,8 +183,8 @@ pub fn process_initialize(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramR
.invoke_signed(&[&[TREASURY, &[args.treasury_bump]]])?;
// Initialize treasury token account.
create_ata(
signer,
create_associated_token_account(
signer_info,
treasury_info,
treasury_tokens_info,
mint_info,

View File

@@ -19,27 +19,16 @@ use update::*;
use upgrade::*;
use ore_api::instruction::*;
use solana_program::{
self, account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
pubkey::Pubkey,
};
solana_program::entrypoint!(process_instruction);
use steel::*;
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
data: &[u8],
) -> ProgramResult {
if program_id.ne(&ore_api::id()) {
return Err(ProgramError::IncorrectProgramId);
}
let (ix, data) = parse_instruction(&ore_api::ID, program_id, data)?;
let (tag, data) = data
.split_first()
.ok_or(ProgramError::InvalidInstructionData)?;
match OreInstruction::try_from(*tag).or(Err(ProgramError::InvalidInstructionData))? {
match ix {
OreInstruction::Claim => process_claim(accounts, data)?,
OreInstruction::Close => process_close(accounts, data)?,
OreInstruction::Mine => process_mine(accounts, data)?,
@@ -53,3 +42,5 @@ pub fn process_instruction(
Ok(())
}
entrypoint!(process_instruction);

View File

@@ -1,56 +1,43 @@
use std::mem::size_of;
use base64::{prelude::BASE64_STANDARD, Engine};
use drillx::Solution;
use ore_api::{
consts::*,
error::OreError,
event::{BoostEvent, MineEvent},
instruction::Mine,
loaders::*,
state::{Bus, Config, Proof},
};
use ore_boost_api::{
loaders::{load_any_boost, load_stake},
state::{Boost, Stake},
};
use ore_utils::{load_signer, load_sysvar};
use ore_api::prelude::*;
use ore_boost_api::state::{Boost, Stake};
#[allow(deprecated)]
use solana_program::{
account_info::AccountInfo,
clock::Clock,
entrypoint::ProgramResult,
keccak::hashv,
program_error::ProgramError,
pubkey::Pubkey,
sanitize::SanitizeError,
serialize_utils::{read_pubkey, read_u16},
slot_hashes::SlotHash,
sysvar::{self, Sysvar},
};
use solana_program::{
log::{self, sol_log},
log::{sol_log, sol_log_data},
program::set_return_data,
};
use steel::*;
/// Mine validates hashes and increments a miner's collectable balance.
pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
pub fn process_mine(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
// Parse args.
let args = Mine::try_from_bytes(data)?;
// Load accounts.
let (required_accounts, optional_accounts) = accounts.split_at(6);
let [signer, bus_info, config_info, proof_info, instructions_sysvar, slot_hashes_sysvar] =
let [signer_info, bus_info, config_info, proof_info, instructions_sysvar, slot_hashes_sysvar] =
required_accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_any_bus(bus_info, true)?;
load_config(config_info, false)?;
load_proof_with_miner(proof_info, signer.key, true)?;
load_sysvar(instructions_sysvar, sysvar::instructions::id())?;
load_sysvar(slot_hashes_sysvar, sysvar::slot_hashes::id())?;
signer_info.is_signer()?;
let bus = bus_info.to_account_mut::<Bus>(&ore_api::ID)?;
let config = config_info
.is_config()?
.to_account::<Config>(&ore_api::ID)?;
let proof = proof_info
.to_account_mut::<Proof>(&ore_api::ID)?
.check_mut(|p| p.miner == *signer_info.key)?;
instructions_sysvar.is_sysvar(&sysvar::instructions::ID)?;
slot_hashes_sysvar.is_sysvar(&sysvar::slot_hashes::ID)?;
// Authenticate the proof account.
//
@@ -59,12 +46,7 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
authenticate(&instructions_sysvar.data.borrow(), proof_info.key)?;
// Validate epoch is active.
let config_data = config_info.data.borrow();
let config = {
use ore_utils::AccountDeserialize;
Config::try_from_bytes(&config_data)?
};
let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?;
let clock = Clock::get()?;
if config
.last_reset_at
.saturating_add(EPOCH_DURATION)
@@ -77,11 +59,6 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
//
// Here we use drillx to validate the provided solution is a valid hash of the challenge.
// If invalid, we return an error.
let mut proof_data = proof_info.data.borrow_mut();
let proof = {
use ore_utils::AccountDeserialize;
Proof::try_from_bytes_mut(&mut proof_data)?
};
let solution = Solution::new(args.digest, args.nonce);
if !solution.is_valid(&proof.challenge) {
return Err(OreError::HashInvalid.into());
@@ -125,11 +102,6 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
// If user has greater than or equal to the max stake on the network, they receive 2x multiplier.
// Any stake less than this will receives between 1x and 2x multipler. The multipler is only active
// if the miner's last stake deposit was more than one minute ago to protect against flash loan attacks.
let mut bus_data = bus_info.data.borrow_mut();
let bus = {
use ore_utils::AccountDeserialize;
Bus::try_from_bytes_mut(&mut bus_data)?
};
if proof.balance.gt(&0) && proof.last_stake_at.saturating_add(ONE_MINUTE).lt(&t) {
// Calculate staking reward.
if config.top_balance.gt(&0) {
@@ -157,8 +129,11 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
// Load optional accounts.
let boost_info = optional_accounts[i * 2].clone();
let stake_info = optional_accounts[i * 2 + 1].clone();
load_any_boost(&boost_info, false)?;
load_stake(&stake_info, &proof.authority, boost_info.key, false)?;
let boost = boost_info.to_account::<Boost>(&ore_boost_api::ID)?;
let stake = stake_info
.to_account::<Stake>(&ore_boost_api::ID)?
.check(|s| s.authority == proof.authority)?
.check(|s| s.boost == *boost_info.key)?;
// Skip if boost is applied twice.
if applied_boosts.contains(boost_info.key) {
@@ -168,22 +143,8 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
// Record this boost has been used.
applied_boosts[i] = *boost_info.key;
// Parse account data.
let boost_data = boost_info.data.borrow();
let boost = {
use ore_boost_api::ore_utils::AccountDeserialize;
Boost::try_from_bytes(&boost_data)?
};
let stake_data = stake_info.data.borrow();
let stake = {
use ore_boost_api::ore_utils::AccountDeserialize;
Stake::try_from_bytes(&stake_data)?
};
let not_expired = boost.expires_at.gt(&t);
let settled = stake.last_stake_at.saturating_add(ONE_MINUTE).le(&t);
// Apply multiplier if boost is not expired and last stake at was more than one minute ago.
if not_expired && settled {
if boost.expires_at.gt(&t) && stake.last_stake_at.saturating_add(ONE_MINUTE).le(&t) {
let multiplier = boost.multiplier.checked_sub(1).unwrap();
let boost_reward = (reward as u128)
.checked_mul(multiplier as u128)
@@ -193,18 +154,19 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
.checked_div(boost.total_stake as u128)
.unwrap() as u64;
reward = reward.checked_add(boost_reward).unwrap();
let boost_event = BoostEvent {
// Log event
sol_log_data(&[(BoostEvent {
mint: boost.mint,
reward: boost_reward,
};
let boost_event = boost_event.to_bytes();
let boost_event = BASE64_STANDARD.encode(boost_event);
sol_log(format!("Boost event: {:}", boost_event).as_str());
})
.to_bytes()]);
}
}
}
// Log base reward after boost rewards for parsing.
log::sol_log(&format!("Base: {}", reward));
// Log base reward after boost rewards.
// Parser looks for base reward first, and then for the variable number of boost rewards.
sol_log(&format!("Base: {}", reward));
// Apply liveness penalty.
//
@@ -264,7 +226,7 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
// Update lifetime stats.
proof.total_hashes = proof.total_hashes.saturating_add(1);
proof.total_rewards = proof.total_rewards.saturating_add(reward);
proof.total_rewards = proof.total_rewards.saturating_add(reward_actual);
// Log the mined rewards.
//

View File

@@ -1,17 +1,8 @@
use std::mem::size_of;
use ore_api::{consts::*, instruction::Open, state::Proof};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo,
clock::Clock,
entrypoint::ProgramResult,
keccak::hashv,
program_error::ProgramError,
slot_hashes::SlotHash,
system_program,
sysvar::{self, Sysvar},
};
use ore_api::prelude::*;
use solana_program::{keccak::hashv, slot_hashes::SlotHash};
use steel::*;
/// Open creates a new proof account to track a miner's state.
pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
@@ -19,39 +10,35 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
let args = Open::try_from_bytes(data)?;
// Load accounts.
let [signer, miner_info, payer_info, proof_info, system_program, slot_hashes_info] = accounts
let [signer_info, miner_info, payer_info, proof_info, system_program, slot_hashes_info] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_any(miner_info, false)?;
load_signer(payer_info)?;
load_uninitialized_pda(
proof_info,
&[PROOF, signer.key.as_ref()],
signer_info.is_signer()?;
payer_info.is_signer()?;
proof_info.is_empty()?.is_writable()?.has_seeds(
&[PROOF, signer_info.key.as_ref()],
args.bump,
&ore_api::id(),
&ore_api::ID,
)?;
load_program(system_program, system_program::id())?;
load_sysvar(slot_hashes_info, sysvar::slot_hashes::id())?;
system_program.is_program(&system_program::ID)?;
slot_hashes_info.is_sysvar(&sysvar::slot_hashes::ID)?;
// Initialize proof.
create_pda(
create_account::<Proof>(
proof_info,
&ore_api::id(),
8 + size_of::<Proof>(),
&[PROOF, signer.key.as_ref(), &[args.bump]],
&ore_api::ID,
&[PROOF, signer_info.key.as_ref(), &[args.bump]],
system_program,
payer_info,
)?;
let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?;
let mut proof_data = proof_info.data.borrow_mut();
proof_data[0] = Proof::discriminator() as u8;
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
proof.authority = *signer.key;
let clock = Clock::get()?;
let proof = proof_info.to_account_mut::<Proof>(&ore_api::ID)?;
proof.authority = *signer_info.key;
proof.balance = 0;
proof.challenge = hashv(&[
signer.key.as_ref(),
signer_info.key.as_ref(),
&slot_hashes_info.data.borrow()[0..size_of::<SlotHash>()],
])
.0;

View File

@@ -1,47 +1,52 @@
use ore_api::{
consts::*,
error::OreError,
loaders::*,
state::{Bus, Config},
};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult,
program_error::ProgramError, program_pack::Pack, sysvar::Sysvar,
};
use spl_token::state::Mint;
use ore_api::prelude::*;
use steel::*;
/// Reset tops up the bus balances, updates the base reward rate, and sets up the ORE program for the next epoch.
pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
// Load accounts.
let [signer, bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, bus_7_info, config_info, mint_info, treasury_info, treasury_tokens_info, token_program] =
let [signer_info, bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, bus_7_info, config_info, mint_info, treasury_info, treasury_tokens_info, token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_bus(bus_0_info, 0, true)?;
load_bus(bus_1_info, 1, true)?;
load_bus(bus_2_info, 2, true)?;
load_bus(bus_3_info, 3, true)?;
load_bus(bus_4_info, 4, true)?;
load_bus(bus_5_info, 5, true)?;
load_bus(bus_6_info, 6, true)?;
load_bus(bus_7_info, 7, true)?;
load_config(config_info, true)?;
load_mint(mint_info, MINT_ADDRESS, true)?;
load_treasury(treasury_info, true)?;
load_treasury_tokens(treasury_tokens_info, true)?;
load_program(token_program, spl_token::id())?;
let busses: [&AccountInfo; BUS_COUNT] = [
bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info,
bus_7_info,
];
signer_info.is_signer()?;
let bus_0 = bus_0_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 0)?;
let bus_1 = bus_1_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 1)?;
let bus_2 = bus_2_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 2)?;
let bus_3 = bus_3_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 3)?;
let bus_4 = bus_4_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 4)?;
let bus_5 = bus_5_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 5)?;
let bus_6 = bus_6_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 6)?;
let bus_7 = bus_7_info
.to_account_mut::<Bus>(&ore_api::ID)?
.check_mut(|b| b.id == 7)?;
let config = config_info
.is_config()?
.to_account_mut::<Config>(&ore_api::ID)?;
let mint = mint_info
.has_address(&MINT_ADDRESS)?
.is_writable()?
.to_mint()?;
treasury_info.is_treasury()?.is_writable()?;
treasury_tokens_info.is_treasury_tokens()?.is_writable()?;
token_program.is_program(&spl_token::ID)?;
// Validate enough time has passed since the last reset.
let mut config_data = config_info.data.borrow_mut();
let config = Config::try_from_bytes_mut(&mut config_data)?;
let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?;
let clock = Clock::get()?;
if config
.last_reset_at
.saturating_add(EPOCH_DURATION)
@@ -54,14 +59,11 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul
config.last_reset_at = clock.unix_timestamp;
// Reset bus accounts and calculate actual rewards mined since last reset.
let busses = [bus_0, bus_1, bus_2, bus_3, bus_4, bus_5, bus_6, bus_7];
let mut total_remaining_rewards = 0u64;
let mut total_theoretical_rewards = 0u64;
let mut top_balance = 0u64;
for i in 0..BUS_COUNT {
// Parse bus account.
let mut bus_data = busses[i].data.borrow_mut();
let bus = Bus::try_from_bytes_mut(&mut bus_data)?;
for bus in busses {
// Track top balance.
if bus.top_balance.gt(&top_balance) {
top_balance = bus.top_balance;
@@ -99,7 +101,6 @@ pub fn process_reset(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul
}
// Max supply check.
let mint = Mint::unpack(&mint_info.data.borrow()).expect("Failed to parse mint");
if mint.supply.ge(&MAX_SUPPLY) {
return Err(OreError::MaxSupply.into());
}

View File

@@ -1,9 +1,5 @@
use ore_api::{consts::*, instruction::Stake, loaders::*, state::Proof};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult,
program_error::ProgramError, sysvar::Sysvar,
};
use ore_api::prelude::*;
use steel::*;
/// Stake deposits ORE into a proof account to earn multiplier.
pub fn process_stake(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
@@ -12,27 +8,32 @@ pub fn process_stake(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
let amount = u64::from_le_bytes(args.amount);
// Load accounts.
let [signer, proof_info, sender_info, treasury_tokens_info, token_program] = accounts else {
let [signer_info, proof_info, sender_info, treasury_tokens_info, token_program] = accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_proof(proof_info, signer.key, true)?;
load_token_account(sender_info, Some(signer.key), &MINT_ADDRESS, true)?;
load_treasury_tokens(treasury_tokens_info, true)?;
load_program(token_program, spl_token::id())?;
signer_info.is_signer()?;
let proof = proof_info
.to_account_mut::<Proof>(&ore_api::ID)?
.check_mut(|p| p.authority == *signer_info.key)?;
sender_info
.is_writable()?
.to_token_account()?
.check(|t| t.owner == *signer_info.key)?
.check(|t| t.mint == MINT_ADDRESS)?;
treasury_tokens_info.is_writable()?.is_treasury_tokens()?;
token_program.is_program(&spl_token::ID)?;
// Update the proof balance.
let mut proof_data = proof_info.data.borrow_mut();
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
proof.balance = proof.balance.checked_add(amount).unwrap();
// Update deposit timestamp.
let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?;
let clock = Clock::get()?;
proof.last_stake_at = clock.unix_timestamp;
// Transfer tokens from signer to treasury.
transfer(
signer,
signer_info,
sender_info,
treasury_tokens_info,
token_program,

View File

@@ -1,22 +1,18 @@
use ore_api::{loaders::*, state::Proof};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
};
use ore_api::prelude::*;
use steel::*;
/// Update changes the miner authority on a proof account.
pub fn process_update(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
// Load accounts.
let [signer, miner_info, proof_info] = accounts else {
let [signer_info, miner_info, proof_info] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_any(miner_info, false)?;
load_proof(proof_info, signer.key, true)?;
signer_info.is_signer()?;
let proof = proof_info
.to_account_mut::<Proof>(&ore_api::ID)?
.check_mut(|p| p.authority == *signer_info.key)?;
// Update the proof's miner authority.
let mut proof_data = proof_info.data.borrow_mut();
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
proof.miner = *miner_info.key;
Ok(())

View File

@@ -1,10 +1,5 @@
use ore_api::{consts::*, error::OreError, instruction::Stake};
use ore_utils::*;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
program_pack::Pack,
};
use spl_token::state::Mint;
use ore_api::prelude::*;
use steel::*;
/// Upgrade allows a user to migrate a v1 token to a v2 token at a 1:1 exchange rate.
pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
@@ -13,17 +8,32 @@ pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResu
let amount = u64::from_le_bytes(args.amount);
// Load accounts
let [signer, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] =
let [signer_info, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_token_account(beneficiary_info, Some(&signer.key), &MINT_ADDRESS, true)?;
load_mint(mint_info, MINT_ADDRESS, true)?;
load_mint(mint_v1_info, MINT_V1_ADDRESS, true)?;
load_token_account(sender_info, Some(signer.key), &MINT_V1_ADDRESS, true)?;
load_program(token_program, spl_token::id())?;
signer_info.is_signer()?;
beneficiary_info
.is_writable()?
.to_token_account()?
.check(|t| t.owner == *signer_info.key)?
.check(|t| t.mint == MINT_ADDRESS)?;
let mint = mint_info
.is_writable()?
.has_address(&MINT_ADDRESS)?
.to_mint()?;
mint_v1_info
.is_writable()?
.has_address(&MINT_V1_ADDRESS)?
.to_mint()?;
sender_info
.is_writable()?
.to_token_account()?
.check(|t| t.owner == *signer_info.key)?
.check(|t| t.mint == MINT_V1_ADDRESS)?;
treasury_info.is_treasury()?;
token_program.is_program(&spl_token::ID)?;
// Burn v1 tokens
solana_program::program::invoke(
@@ -31,15 +41,15 @@ pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResu
&spl_token::id(),
sender_info.key,
mint_v1_info.key,
signer.key,
&[signer.key],
signer_info.key,
&[signer_info.key],
amount,
)?,
&[
token_program.clone(),
sender_info.clone(),
mint_v1_info.clone(),
signer.clone(),
signer_info.clone(),
],
)?;
@@ -48,14 +58,11 @@ pub fn process_upgrade(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResu
let amount_to_mint = amount.saturating_mul(100);
// Cap at max supply.
let mint_data = mint_info.data.borrow();
let mint = Mint::unpack(&mint_data)?;
if mint.supply.saturating_add(amount_to_mint).gt(&MAX_SUPPLY) {
return Err(OreError::MaxSupply.into());
}
// Mint to the beneficiary account
drop(mint_data);
mint_to_signed(
mint_info,
beneficiary_info,

View File

@@ -1,20 +0,0 @@
[package]
name = "ore-utils"
description = "Utils for building ORE programs"
version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
documentation.workspace = true
repository.workspace = true
keywords.workspace = true
[features]
deafult = []
spl = ["spl-token", "spl-associated-token-account"]
[dependencies]
bytemuck.workspace = true
solana-program.workspace = true
spl-token = { workspace = true, optional = true }
spl-associated-token-account = { workspace = true, optional = true }

View File

@@ -1,214 +0,0 @@
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey, rent::Rent,
sysvar::Sysvar,
};
/// Creates a new pda.
#[inline(always)]
pub fn create_pda<'a, 'info>(
target_account: &'a AccountInfo<'info>,
owner: &Pubkey,
space: usize,
pda_seeds: &[&[u8]],
system_program: &'a AccountInfo<'info>,
payer: &'a AccountInfo<'info>,
) -> ProgramResult {
let rent = Rent::get()?;
if target_account.lamports().eq(&0) {
// If balance is zero, create account
solana_program::program::invoke_signed(
&solana_program::system_instruction::create_account(
payer.key,
target_account.key,
rent.minimum_balance(space),
space as u64,
owner,
),
&[
payer.clone(),
target_account.clone(),
system_program.clone(),
],
&[pda_seeds],
)?;
} else {
// Otherwise, if balance is nonzero:
// 1) transfer sufficient lamports for rent exemption
let rent_exempt_balance = rent
.minimum_balance(space)
.saturating_sub(target_account.lamports());
if rent_exempt_balance.gt(&0) {
solana_program::program::invoke(
&solana_program::system_instruction::transfer(
payer.key,
target_account.key,
rent_exempt_balance,
),
&[
payer.clone(),
target_account.clone(),
system_program.clone(),
],
)?;
}
// 2) allocate space for the account
solana_program::program::invoke_signed(
&solana_program::system_instruction::allocate(target_account.key, space as u64),
&[target_account.clone(), system_program.clone()],
&[pda_seeds],
)?;
// 3) assign our program as the owner
solana_program::program::invoke_signed(
&solana_program::system_instruction::assign(target_account.key, owner),
&[target_account.clone(), system_program.clone()],
&[pda_seeds],
)?;
}
Ok(())
}
#[cfg(feature = "spl")]
#[inline(always)]
pub fn create_ata<'info>(
funder_info: &AccountInfo<'info>,
owner_info: &AccountInfo<'info>,
token_account_info: &AccountInfo<'info>,
mint_info: &AccountInfo<'info>,
system_program: &AccountInfo<'info>,
token_program: &AccountInfo<'info>,
associated_token_program: &AccountInfo<'info>,
) -> ProgramResult {
solana_program::program::invoke(
&spl_associated_token_account::instruction::create_associated_token_account(
funder_info.key,
owner_info.key,
mint_info.key,
&spl_token::id(),
),
&[
funder_info.clone(),
token_account_info.clone(),
owner_info.clone(),
mint_info.clone(),
system_program.clone(),
token_program.clone(),
associated_token_program.clone(),
],
)
}
#[cfg(feature = "spl")]
#[inline(always)]
pub fn transfer<'info>(
authority_info: &AccountInfo<'info>,
from_info: &AccountInfo<'info>,
to_info: &AccountInfo<'info>,
token_program: &AccountInfo<'info>,
amount: u64,
) -> ProgramResult {
solana_program::program::invoke(
&spl_token::instruction::transfer(
&spl_token::id(),
from_info.key,
to_info.key,
authority_info.key,
&[authority_info.key],
amount,
)?,
&[
token_program.clone(),
from_info.clone(),
to_info.clone(),
authority_info.clone(),
],
)
}
#[cfg(feature = "spl")]
#[inline(always)]
pub fn transfer_signed<'info>(
authority_info: &AccountInfo<'info>,
from_info: &AccountInfo<'info>,
to_info: &AccountInfo<'info>,
token_program: &AccountInfo<'info>,
amount: u64,
signer_seeds: &[&[&[u8]]],
) -> ProgramResult {
solana_program::program::invoke_signed(
&spl_token::instruction::transfer(
&spl_token::id(),
from_info.key,
to_info.key,
authority_info.key,
&[authority_info.key],
amount,
)?,
&[
token_program.clone(),
from_info.clone(),
to_info.clone(),
authority_info.clone(),
],
signer_seeds,
)
}
#[cfg(feature = "spl")]
#[inline(always)]
pub fn mint_to_signed<'info>(
mint_info: &AccountInfo<'info>,
to_info: &AccountInfo<'info>,
authority_info: &AccountInfo<'info>,
token_program: &AccountInfo<'info>,
amount: u64,
signer_seeds: &[&[&[u8]]],
) -> ProgramResult {
solana_program::program::invoke_signed(
&spl_token::instruction::mint_to(
&spl_token::id(),
mint_info.key,
to_info.key,
authority_info.key,
&[authority_info.key],
amount,
)?,
&[
token_program.clone(),
mint_info.clone(),
to_info.clone(),
authority_info.clone(),
],
signer_seeds,
)
}
#[cfg(feature = "spl")]
#[inline(always)]
pub fn burn<'info>(
token_account_info: &AccountInfo<'info>,
mint_info: &AccountInfo<'info>,
authority_info: &AccountInfo<'info>,
token_program: &AccountInfo<'info>,
amount: u64,
) -> ProgramResult {
solana_program::program::invoke(
&spl_token::instruction::burn(
&spl_token::id(),
token_account_info.key,
mint_info.key,
authority_info.key,
&[authority_info.key],
amount,
)?,
&[
token_program.clone(),
token_account_info.clone(),
mint_info.clone(),
authority_info.clone(),
],
)
}

View File

@@ -1,8 +0,0 @@
mod cpi;
mod loaders;
pub mod macros;
mod traits;
pub use cpi::*;
pub use loaders::*;
pub use traits::*;

View File

@@ -1,249 +0,0 @@
#[cfg(feature = "spl")]
use solana_program::program_pack::Pack;
use solana_program::{
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, system_program, sysvar,
};
#[cfg(feature = "spl")]
use spl_token::state::Mint;
/// Errors if:
/// - Account is not a signer.
pub fn load_signer(info: &AccountInfo<'_>) -> Result<(), ProgramError> {
if !info.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
Ok(())
}
/// Errors if:
/// - Address does not match PDA derived from provided seeds.
/// - Cannot load as an uninitialized account.
pub fn load_uninitialized_pda(
info: &AccountInfo<'_>,
seeds: &[&[u8]],
bump: u8,
program_id: &Pubkey,
) -> Result<(), ProgramError> {
let pda = Pubkey::find_program_address(seeds, program_id);
if info.key.ne(&pda.0) {
return Err(ProgramError::InvalidSeeds);
}
if bump.ne(&pda.1) {
return Err(ProgramError::InvalidSeeds);
}
load_system_account(info, true)
}
/// Errors if:
/// - Owner is not the system program.
/// - Data is not empty.
/// - Account is not writable.
pub fn load_system_account(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&system_program::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if !info.data_is_empty() {
return Err(ProgramError::AccountAlreadyInitialized);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not the sysvar address.
/// - Account cannot load with the expected address.
pub fn load_sysvar(info: &AccountInfo<'_>, key: Pubkey) -> Result<(), ProgramError> {
if info.owner.ne(&sysvar::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
load_account(info, key, false)
}
/// Errors if:
/// - Address does not match the expected value.
/// - Expected to be writable, but is not.
pub fn load_account(
info: &AccountInfo<'_>,
key: Pubkey,
is_writable: bool,
) -> Result<(), ProgramError> {
if info.key.ne(&key) {
return Err(ProgramError::InvalidAccountData);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Address does not match the expected value.
/// - Account is not executable.
pub fn load_program(info: &AccountInfo<'_>, key: Pubkey) -> Result<(), ProgramError> {
if info.key.ne(&key) {
return Err(ProgramError::IncorrectProgramId);
}
if !info.executable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Account is not writable.
pub fn load_any(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not SPL token program.
/// - Address does not match the expected mint address.
/// - Data is empty.
/// - Data cannot deserialize into a mint account.
/// - Expected to be writable, but is not.
#[cfg(feature = "spl")]
pub fn load_mint(
info: &AccountInfo<'_>,
address: Pubkey,
is_writable: bool,
) -> Result<(), ProgramError> {
if info.owner.ne(&spl_token::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.key.ne(&address) {
return Err(ProgramError::InvalidSeeds);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
Mint::unpack(&info.data.borrow())?;
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not SPL token program.
/// - Data is empty.
/// - Data cannot deserialize into a mint account.
/// - Expected to be writable, but is not.
#[cfg(feature = "spl")]
pub fn load_any_mint(info: &AccountInfo<'_>, is_writable: bool) -> Result<(), ProgramError> {
if info.owner.ne(&spl_token::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
Mint::unpack(&info.data.borrow())?;
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not SPL token program.
/// - Data is empty.
/// - Data cannot deserialize into a token account.
/// - Token account owner does not match the expected owner address.
/// - Token account mint does not match the expected mint address.
/// - Expected to be writable, but is not.
#[cfg(feature = "spl")]
pub fn load_token_account(
info: &AccountInfo<'_>,
owner: Option<&Pubkey>,
mint: &Pubkey,
is_writable: bool,
) -> Result<(), ProgramError> {
if info.owner.ne(&spl_token::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
let account_data = info.data.borrow();
let account = spl_token::state::Account::unpack(&account_data)?;
if account.mint.ne(&mint) {
return Err(ProgramError::InvalidAccountData);
}
if let Some(owner) = owner {
if account.owner.ne(owner) {
return Err(ProgramError::InvalidAccountData);
}
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
/// Errors if:
/// - Owner is not SPL token program.
/// - Data is empty.
/// - Data cannot deserialize into a token account.
/// - Address does not match the expected associated token address.
/// - Expected to be writable, but is not.
#[cfg(feature = "spl")]
pub fn load_associated_token_account(
info: &AccountInfo<'_>,
owner: &Pubkey,
mint: &Pubkey,
is_writable: bool,
) -> Result<(), ProgramError> {
if info.owner.ne(&spl_token::id()) {
return Err(ProgramError::InvalidAccountOwner);
}
if info.data_is_empty() {
return Err(ProgramError::UninitializedAccount);
}
let account_data = info.data.borrow();
let _ = spl_token::state::Account::unpack(&account_data)?;
let address = spl_associated_token_account::get_associated_token_address(owner, mint);
if info.key.ne(&address) {
return Err(ProgramError::InvalidSeeds);
}
if is_writable && !info.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}

View File

@@ -1,120 +0,0 @@
#[macro_export]
macro_rules! impl_to_bytes {
($struct_name:ident) => {
impl $struct_name {
pub fn to_bytes(&self) -> &[u8] {
bytemuck::bytes_of(self)
}
}
};
}
#[macro_export]
macro_rules! impl_from_bytes {
($struct_name:ident) => {
impl $struct_name {
pub fn from_bytes(data: &[u8]) -> &Self {
bytemuck::from_bytes::<Self>(data)
}
}
};
}
#[macro_export]
macro_rules! impl_account_from_bytes {
($struct_name:ident) => {
impl $crate::AccountDeserialize for $struct_name {
fn try_from_bytes(
data: &[u8],
) -> Result<&Self, solana_program::program_error::ProgramError> {
if Self::discriminator().ne(&data[0]) {
return Err(solana_program::program_error::ProgramError::InvalidAccountData);
}
bytemuck::try_from_bytes::<Self>(&data[8..]).or(Err(
solana_program::program_error::ProgramError::InvalidAccountData,
))
}
fn try_from_bytes_mut(
data: &mut [u8],
) -> Result<&mut Self, solana_program::program_error::ProgramError> {
if Self::discriminator().ne(&data[0]) {
return Err(solana_program::program_error::ProgramError::InvalidAccountData);
}
bytemuck::try_from_bytes_mut::<Self>(&mut data[8..]).or(Err(
solana_program::program_error::ProgramError::InvalidAccountData,
))
}
}
};
}
#[macro_export]
macro_rules! impl_instruction_from_bytes {
($struct_name:ident) => {
impl $struct_name {
pub fn try_from_bytes(
data: &[u8],
) -> Result<&Self, solana_program::program_error::ProgramError> {
bytemuck::try_from_bytes::<Self>(data).or(Err(
solana_program::program_error::ProgramError::InvalidInstructionData,
))
}
}
};
}
#[macro_export]
macro_rules! account {
($discriminator_name:ident, $struct_name:ident) => {
$crate::impl_to_bytes!($struct_name);
$crate::impl_account_from_bytes!($struct_name);
impl $crate::Discriminator for $struct_name {
fn discriminator() -> u8 {
$discriminator_name::$struct_name.into()
}
}
};
}
#[macro_export]
macro_rules! error {
($struct_name:ident) => {
impl From<$struct_name> for solana_program::program_error::ProgramError {
fn from(e: $struct_name) -> Self {
solana_program::program_error::ProgramError::Custom(e as u32)
}
}
};
}
#[macro_export]
macro_rules! event {
($struct_name:ident) => {
$crate::impl_to_bytes!($struct_name);
$crate::impl_from_bytes!($struct_name);
};
}
#[macro_export]
macro_rules! instruction {
($discriminator_name:ident, $struct_name:ident) => {
$crate::impl_instruction_from_bytes!($struct_name);
impl $crate::Discriminator for $struct_name {
fn discriminator() -> u8 {
$discriminator_name::$struct_name as u8
}
}
impl $struct_name {
pub fn to_bytes(&self) -> Vec<u8> {
[
[$discriminator_name::$struct_name as u8].to_vec(),
bytemuck::bytes_of(self).to_vec(),
]
.concat()
}
}
};
}

View File

@@ -1,10 +0,0 @@
use solana_program::program_error::ProgramError;
pub trait AccountDeserialize {
fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError>;
fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError>;
}
pub trait Discriminator {
fn discriminator() -> u8;
}