diff --git a/Cargo.lock b/Cargo.lock index 775dab6..e6baaec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", ] diff --git a/Cargo.toml b/Cargo.toml index eb9ee67..060e836 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" - - diff --git a/api/Cargo.toml b/api/Cargo.toml index aad2498..d11cc5a 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -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 diff --git a/api/src/error.rs b/api/src/error.rs index b0653ba..33fdb75 100644 --- a/api/src/error.rs +++ b/api/src/error.rs @@ -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)] diff --git a/api/src/event.rs b/api/src/event.rs index 096ee76..3dbb467 100644 --- a/api/src/event.rs +++ b/api/src/event.rs @@ -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); diff --git a/api/src/instruction.rs b/api/src/instruction.rs index 7010646..141df9a 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -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)] diff --git a/api/src/lib.rs b/api/src/lib.rs index e7bc19e..5389416 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -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"); diff --git a/api/src/loaders.rs b/api/src/loaders.rs index 881ca5d..ebc7383 100644 --- a/api/src/loaders.rs +++ b/api/src/loaders.rs @@ -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::(&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::(&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) } diff --git a/api/src/sdk.rs b/api/src/sdk.rs index 301d033..e9d20eb 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -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, ) -> 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, diff --git a/api/src/state/bus.rs b/api/src/state/bus.rs index 0d07296..bf32edc 100644 --- a/api/src/state/bus.rs +++ b/api/src/state/bus.rs @@ -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); diff --git a/api/src/state/config.rs b/api/src/state/config.rs index 35dded5..52b21cc 100644 --- a/api/src/state/config.rs +++ b/api/src/state/config.rs @@ -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); diff --git a/api/src/state/mod.rs b/api/src/state/mod.rs index 6803553..20baa13 100644 --- a/api/src/state/mod.rs +++ b/api/src/state/mod.rs @@ -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()) +} diff --git a/api/src/state/proof.rs b/api/src/state/proof.rs index ba68660..733e115 100644 --- a/api/src/state/proof.rs +++ b/api/src/state/proof.rs @@ -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); diff --git a/api/src/state/treasury.rs b/api/src/state/treasury.rs index 20c34fc..2268ae0 100644 --- a/api/src/state/treasury.rs +++ b/api/src/state/treasury.rs @@ -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); diff --git a/program/Cargo.toml b/program/Cargo.toml index acfae67..0118d8d 100644 --- a/program/Cargo.toml +++ b/program/Cargo.toml @@ -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" diff --git a/program/src/claim.rs b/program/src/claim.rs index aedf620..c4a9201 100644 --- a/program/src/claim.rs +++ b/program/src/claim.rs @@ -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::(&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) diff --git a/program/src/close.rs b/program/src/close.rs index c12150c..dd58ead 100644 --- a/program/src/close.rs +++ b/program/src/close.rs @@ -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::(&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(()) diff --git a/program/src/initialize.rs b/program/src/initialize.rs index 6759876..4d7d8b3 100644 --- a/program/src/initialize.rs +++ b/program/src/initialize.rs @@ -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_infos[i], - &ore_api::id(), - 8 + size_of::(), + &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::(&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_info, - &ore_api::id(), - 8 + size_of::(), + &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::(&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_info, - &ore_api::id(), - 8 + size_of::(), + &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, diff --git a/program/src/lib.rs b/program/src/lib.rs index 0bb046f..1523004 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -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); diff --git a/program/src/mine.rs b/program/src/mine.rs index ac60892..be4c55b 100644 --- a/program/src/mine.rs +++ b/program/src/mine.rs @@ -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::(&ore_api::ID)?; + let config = config_info + .is_config()? + .to_account::(&ore_api::ID)?; + let proof = proof_info + .to_account_mut::(&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::(&ore_boost_api::ID)?; + let stake = stake_info + .to_account::(&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. // diff --git a/program/src/open.rs b/program/src/open.rs index 4ded87c..bc9c9f3 100644 --- a/program/src/open.rs +++ b/program/src/open.rs @@ -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_info, - &ore_api::id(), - 8 + size_of::(), - &[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::(&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::()], ]) .0; diff --git a/program/src/reset.rs b/program/src/reset.rs index eda9489..28a736c 100644 --- a/program/src/reset.rs +++ b/program/src/reset.rs @@ -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::(&ore_api::ID)? + .check_mut(|b| b.id == 0)?; + let bus_1 = bus_1_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 1)?; + let bus_2 = bus_2_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 2)?; + let bus_3 = bus_3_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 3)?; + let bus_4 = bus_4_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 4)?; + let bus_5 = bus_5_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 5)?; + let bus_6 = bus_6_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 6)?; + let bus_7 = bus_7_info + .to_account_mut::(&ore_api::ID)? + .check_mut(|b| b.id == 7)?; + let config = config_info + .is_config()? + .to_account_mut::(&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()); } diff --git a/program/src/stake.rs b/program/src/stake.rs index e64f5b3..7a42d80 100644 --- a/program/src/stake.rs +++ b/program/src/stake.rs @@ -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::(&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, diff --git a/program/src/update.rs b/program/src/update.rs index c5a21e7..4f153a6 100644 --- a/program/src/update.rs +++ b/program/src/update.rs @@ -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::(&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(()) diff --git a/program/src/upgrade.rs b/program/src/upgrade.rs index a167872..74090d0 100644 --- a/program/src/upgrade.rs +++ b/program/src/upgrade.rs @@ -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, diff --git a/audits/fuzzland.pdf b/security/fuzzland-audit.pdf similarity index 100% rename from audits/fuzzland.pdf rename to security/fuzzland-audit.pdf diff --git a/audits/ottersec.pdf b/security/ottersec-audit.pdf similarity index 100% rename from audits/ottersec.pdf rename to security/ottersec-audit.pdf diff --git a/utils/Cargo.toml b/utils/Cargo.toml deleted file mode 100644 index 2af4092..0000000 --- a/utils/Cargo.toml +++ /dev/null @@ -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 } diff --git a/utils/src/cpi.rs b/utils/src/cpi.rs deleted file mode 100644 index bce2c8e..0000000 --- a/utils/src/cpi.rs +++ /dev/null @@ -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(), - ], - ) -} diff --git a/utils/src/lib.rs b/utils/src/lib.rs deleted file mode 100644 index d4c963a..0000000 --- a/utils/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod cpi; -mod loaders; -pub mod macros; -mod traits; - -pub use cpi::*; -pub use loaders::*; -pub use traits::*; diff --git a/utils/src/loaders.rs b/utils/src/loaders.rs deleted file mode 100644 index 72681fe..0000000 --- a/utils/src/loaders.rs +++ /dev/null @@ -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(()) -} diff --git a/utils/src/macros.rs b/utils/src/macros.rs deleted file mode 100644 index 1bda272..0000000 --- a/utils/src/macros.rs +++ /dev/null @@ -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::(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::(&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::(&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::(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 { - [ - [$discriminator_name::$struct_name as u8].to_vec(), - bytemuck::bytes_of(self).to_vec(), - ] - .concat() - } - } - }; -} diff --git a/utils/src/traits.rs b/utils/src/traits.rs deleted file mode 100644 index 755a5fe..0000000 --- a/utils/src/traits.rs +++ /dev/null @@ -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; -}