diff --git a/Cargo.lock b/Cargo.lock index bd9c8907..af049df2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anyhow" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c" + [[package]] name = "arrayref" version = "0.3.6" @@ -76,6 +82,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" +[[package]] +name = "async-trait" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", +] + [[package]] name = "atty" version = "0.2.14" @@ -217,7 +234,7 @@ checksum = "b2d74755d937d261d5e9bdef87e0addfbc1ace0214f7776f21532d6e97325356" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -226,9 +243,9 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c9f966cb7a42c8ed83546ef481bc1d1dec888fe5f84a4737d5c2094a483e41e" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -237,9 +254,9 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5df2543b56ebc2b4493e70d024ebde2cbb48d97bf7b1a16318eff30bd02669b8" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -293,6 +310,12 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +[[package]] +name = "bytes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0dcbc35f504eb6fc275a6d20e4ebcda18cf50d40ba6fabff8c711fa16cb3b16" + [[package]] name = "bzip2" version = "0.3.3" @@ -324,11 +347,11 @@ dependencies = [ "heck", "indexmap", "log", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", "serde", "serde_json", - "syn 1.0.41", + "syn 1.0.48", "tempfile", "toml", ] @@ -364,14 +387,25 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.13" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ + "libc", "num-integer", "num-traits", "serde", "time", + "winapi 0.3.9", +] + +[[package]] +name = "chrono-humanize" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0a4c32145b4db85fe1c4f2b125a4f9493769df424f5f84baf6b04ea8eaf33c9" +dependencies = [ + "chrono", ] [[package]] @@ -407,6 +441,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "cloudabi" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" +dependencies = [ + "bitflags", +] + [[package]] name = "combine" version = "2.5.2" @@ -638,19 +681,6 @@ dependencies = [ "subtle 2.2.3", ] -[[package]] -name = "curve25519-dalek" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" -dependencies = [ - "byteorder", - "digest 0.8.1", - "rand_core", - "subtle 2.2.3", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "2.1.0" @@ -665,6 +695,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core", + "subtle 2.2.3", + "zeroize", +] + [[package]] name = "curve25519-dalek" version = "3.0.0" @@ -695,9 +738,9 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -855,9 +898,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", "synstructure", ] @@ -946,6 +989,21 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +[[package]] +name = "futures" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.5" @@ -953,6 +1011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -961,6 +1020,17 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" +[[package]] +name = "futures-executor" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.5" @@ -974,9 +1044,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -1000,12 +1070,14 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", + "futures-sink", "futures-task", "memchr", - "pin-project", + "pin-project 0.4.23", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1102,7 +1174,7 @@ dependencies = [ "indexmap", "slab", "tokio 0.2.22", - "tokio-util", + "tokio-util 0.3.1", "tracing", ] @@ -1237,7 +1309,7 @@ dependencies = [ "http-body", "httparse", "itoa", - "pin-project", + "pin-project 0.4.23", "socket2", "time", "tokio 0.2.22", @@ -1304,6 +1376,15 @@ dependencies = [ "bytes 0.5.6", ] +[[package]] +name = "instant" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -1390,7 +1471,7 @@ version = "15.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0745a6379e3edc893c84ec203589790774e4247420033e71a76d3ab4687991fa" dependencies = [ - "futures", + "futures 0.1.29", "log", "serde", "serde_derive", @@ -1469,6 +1550,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lock_api" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.8" @@ -1565,12 +1655,25 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.1", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8962c171f57fcfffa53f4df1bb15ec4c8cf26a7569459c9ceb62d94aab0d9584" +dependencies = [ + "libc", + "log", + "miow 0.3.5", + "ntapi", + "winapi 0.3.9", +] + [[package]] name = "mio-uds" version = "0.6.8" @@ -1579,7 +1682,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", - "mio", + "mio 0.6.22", ] [[package]] @@ -1594,6 +1697,16 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" +dependencies = [ + "socket2", + "winapi 0.3.9", +] + [[package]] name = "native-tls" version = "0.2.4" @@ -1636,15 +1749,24 @@ dependencies = [ "void", ] +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "num-derive" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -1693,9 +1815,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -1781,9 +1903,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77cb63e282343037499f6fd51c1e1964b6c40113b422f076632d0d192a4180de" dependencies = [ "Inflector", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -1792,7 +1914,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api", + "lock_api 0.3.4", "parking_lot_core 0.6.2", "rustc_version", ] @@ -1803,10 +1925,21 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ - "lock_api", + "lock_api 0.3.4", "parking_lot_core 0.7.2", ] +[[package]] +name = "parking_lot" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" +dependencies = [ + "instant", + "lock_api 0.4.1", + "parking_lot_core 0.8.0", +] + [[package]] name = "parking_lot_core" version = "0.6.2" @@ -1814,7 +1947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ "cfg-if 0.1.10", - "cloudabi", + "cloudabi 0.0.3", "libc", "redox_syscall", "rustc_version", @@ -1829,7 +1962,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ "cfg-if 0.1.10", - "cloudabi", + "cloudabi 0.0.3", + "libc", + "redox_syscall", + "smallvec 1.4.2", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi 0.1.0", + "instant", "libc", "redox_syscall", "smallvec 1.4.2", @@ -1886,7 +2034,16 @@ version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa" dependencies = [ - "pin-project-internal", + "pin-project-internal 0.4.23", +] + +[[package]] +name = "pin-project" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" +dependencies = [ + "pin-project-internal 1.0.1", ] [[package]] @@ -1895,9 +2052,20 @@ version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", ] [[package]] @@ -1962,9 +2130,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ "unicode-xid 0.2.0", ] @@ -1990,7 +2158,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", ] [[package]] @@ -2204,9 +2372,9 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9bdc5e856e51e685846fb6c13a1f5e5432946c2c90501bdc76a1319f19e29da" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -2255,9 +2423,9 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b12bd20b94c7cdfda8c7ba9b92ad0d9a56e3fa018c25fca83b51aa664c9b4c0d" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -2350,9 +2518,9 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -2426,6 +2594,15 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "signal-hook-registry" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "1.2.2" @@ -2488,6 +2665,51 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-banks-client" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f30acda71181312c1b4c90e29d5a851f46b682a13459532a8a770a0a9693f7" +dependencies = [ + "async-trait", + "bincode", + "futures 0.3.5", + "solana-banks-interface", + "solana-sdk", + "tarpc", + "tokio 0.3.2", + "tokio-serde", +] + +[[package]] +name = "solana-banks-interface" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e184ad7f588ab856eb59239f0b97bb8293b9dc951d6d0361848b17b569c739f" +dependencies = [ + "serde", + "solana-sdk", + "tarpc", +] + +[[package]] +name = "solana-banks-server" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3365d7f0fb021d56916b2a7ee41326a204abf3b72f8f342b51216a968d22939" +dependencies = [ + "bincode", + "futures 0.3.5", + "log", + "solana-banks-interface", + "solana-metrics", + "solana-runtime", + "solana-sdk", + "tarpc", + "tokio 0.3.2", + "tokio-serde", +] + [[package]] name = "solana-bpf-loader-program" version = "1.4.4" @@ -2622,7 +2844,7 @@ dependencies = [ "reqwest", "serde", "syn 0.15.44", - "syn 1.0.41", + "syn 1.0.48", "tokio 0.1.22", "winapi 0.3.9", ] @@ -2654,10 +2876,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c84e6316d0b71d60ff34d2cc1a25521f6cb605111590a61e9baa768ac1234d4" dependencies = [ "lazy_static", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", "rustc_version", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -2751,6 +2973,25 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-program-test" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0f3ca77a13f378ac7d5c12f91d09835b3091a4de4e061f6f49a8c3699933ec" +dependencies = [ + "base64 0.12.3", + "chrono", + "chrono-humanize", + "log", + "solana-banks-client", + "solana-banks-server", + "solana-bpf-loader-program", + "solana-logger", + "solana-program", + "solana-runtime", + "solana-sdk", +] + [[package]] name = "solana-rayon-threadlimit" version = "1.4.4" @@ -2883,10 +3124,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8da0dcb182f9631a69b4d6de69f82f0aa8bf2350c666122b9fad99380547ccc" dependencies = [ "bs58", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", "rustversion", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -3011,6 +3252,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spl-associated-token-account" +version = "1.0.0" +dependencies = [ + "solana-program", + "solana-program-test", + "solana-sdk", + "spl-token 2.0.8", + "tokio 0.3.2", +] + [[package]] name = "spl-memo" version = "1.0.9" @@ -3172,6 +3424,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.8.0" @@ -3209,11 +3467,11 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.41" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", "unicode-xid 0.2.0", ] @@ -3224,9 +3482,9 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", "unicode-xid 0.2.0", ] @@ -3242,6 +3500,38 @@ dependencies = [ "xattr", ] +[[package]] +name = "tarpc" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1035e0e1b7064c1080702a8a5b3d044a3dea10a1096766be6f5c22580096fa75" +dependencies = [ + "anyhow", + "fnv", + "futures 0.3.5", + "humantime 2.0.1", + "log", + "pin-project 1.0.1", + "rand", + "serde", + "static_assertions", + "tarpc-plugins", + "tokio 0.3.2", + "tokio-serde", + "tokio-util 0.4.0", +] + +[[package]] +name = "tarpc-plugins" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbaf92ceea0a2ab555bea18a47a891e46ba2d6f930ec9506771662f4ab82bb7" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", +] + [[package]] name = "tempfile" version = "3.1.0" @@ -3319,9 +3609,9 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", ] [[package]] @@ -3372,8 +3662,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes 0.4.12", - "futures", - "mio", + "futures 0.1.29", + "mio 0.6.22", "num_cpus", "tokio-codec", "tokio-current-thread", @@ -3401,12 +3691,34 @@ dependencies = [ "iovec", "lazy_static", "memchr", - "mio", + "mio 0.6.22", "num_cpus", "pin-project-lite", "slab", ] +[[package]] +name = "tokio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f1b20504fd0aa9dab3ae17e8c4dd9431e5e08fd6921689f9745a4004883a17" +dependencies = [ + "bytes 0.6.0", + "fnv", + "futures-core", + "lazy_static", + "libc", + "memchr", + "mio 0.7.5", + "num_cpus", + "parking_lot 0.11.0", + "pin-project-lite", + "signal-hook-registry", + "slab", + "tokio-macros", + "winapi 0.3.9", +] + [[package]] name = "tokio-codec" version = "0.1.2" @@ -3414,7 +3726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ "bytes 0.4.12", - "futures", + "futures 0.1.29", "tokio-io", ] @@ -3424,7 +3736,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures", + "futures 0.1.29", "tokio-executor", ] @@ -3435,7 +3747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ "crossbeam-utils 0.7.2", - "futures", + "futures 0.1.29", ] [[package]] @@ -3444,7 +3756,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures", + "futures 0.1.29", "tokio-io", "tokio-threadpool", ] @@ -3456,10 +3768,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", - "futures", + "futures 0.1.29", "log", ] +[[package]] +name = "tokio-macros" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21d30fdbb5dc2d8f91049691aa1a9d4d4ae422a21c334ce8936e5886d30c5c45" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", + "syn 1.0.48", +] + [[package]] name = "tokio-reactor" version = "0.1.12" @@ -3467,10 +3790,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ "crossbeam-utils 0.7.2", - "futures", + "futures 0.1.29", "lazy_static", "log", - "mio", + "mio 0.6.22", "num_cpus", "parking_lot 0.9.0", "slab", @@ -3491,6 +3814,20 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-serde" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebdd897b01021779294eb09bb3b52b6e11b0747f9f7e333a84bef532b656de99" +dependencies = [ + "bincode", + "bytes 0.5.6", + "derivative", + "futures 0.3.5", + "pin-project 0.4.23", + "serde", +] + [[package]] name = "tokio-sync" version = "0.1.8" @@ -3498,7 +3835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ "fnv", - "futures", + "futures 0.1.29", ] [[package]] @@ -3508,9 +3845,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ "bytes 0.4.12", - "futures", + "futures 0.1.29", "iovec", - "mio", + "mio 0.6.22", "tokio-io", "tokio-reactor", ] @@ -3524,7 +3861,7 @@ dependencies = [ "crossbeam-deque 0.7.3", "crossbeam-queue", "crossbeam-utils 0.7.2", - "futures", + "futures 0.1.29", "lazy_static", "log", "num_cpus", @@ -3539,7 +3876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ "crossbeam-utils 0.7.2", - "futures", + "futures 0.1.29", "slab", "tokio-executor", ] @@ -3551,9 +3888,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ "bytes 0.4.12", - "futures", + "futures 0.1.29", "log", - "mio", + "mio 0.6.22", "tokio-codec", "tokio-io", "tokio-reactor", @@ -3566,11 +3903,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes 0.4.12", - "futures", + "futures 0.1.29", "iovec", "libc", "log", - "mio", + "mio 0.6.22", "mio-uds", "tokio-codec", "tokio-io", @@ -3591,6 +3928,20 @@ dependencies = [ "tokio 0.2.22", ] +[[package]] +name = "tokio-util" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24793699f4665ba0416ed287dc794fe6b11a4aa5e4e95b58624f45f6c46b97d4" +dependencies = [ + "bytes 0.5.6", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio 0.3.2", +] + [[package]] name = "toml" version = "0.5.6" @@ -3810,9 +4161,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", "wasm-bindgen-shared", ] @@ -3844,9 +4195,9 @@ version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3981,9 +4332,9 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" dependencies = [ - "proc-macro2 1.0.19", + "proc-macro2 1.0.24", "quote 1.0.7", - "syn 1.0.41", + "syn 1.0.48", "synstructure", ] diff --git a/Cargo.toml b/Cargo.toml index 417ceb28..cb79d890 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "associated-token-account/program", "memo/program", "shared-memory/program", "stake-pool/program", diff --git a/associated-token-account/program/Cargo.toml b/associated-token-account/program/Cargo.toml new file mode 100644 index 00000000..0730dcc9 --- /dev/null +++ b/associated-token-account/program/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "spl-associated-token-account" +version = "1.0.0" +description = "SPL Associated Token Account" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana-program-library" +license = "Apache-2.0" +edition = "2018" + +[features] +exclude_entrypoint = [] + +[dependencies] +solana-program = "1.4.4" +spl-token = { path = "../../token/program", features = ["exclude_entrypoint"] } + +[dev-dependencies] +solana-program-test = "1.4.4" +solana-sdk = "1.4.4" +tokio = { version = "0.3", features = ["macros"]} + +[lib] +crate-type = ["cdylib", "lib"] diff --git a/associated-token-account/program/Xargo.toml b/associated-token-account/program/Xargo.toml new file mode 100644 index 00000000..1744f098 --- /dev/null +++ b/associated-token-account/program/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] \ No newline at end of file diff --git a/associated-token-account/program/build.rs b/associated-token-account/program/build.rs new file mode 100644 index 00000000..c162da37 --- /dev/null +++ b/associated-token-account/program/build.rs @@ -0,0 +1,21 @@ +use std::process::{exit, Command}; + +fn main() { + if std::env::var("XARGO").is_err() + && std::env::var("RUSTC_WRAPPER").is_err() + && std::env::var("RUSTC_WORKSPACE_WRAPPER").is_err() + { + println!( + "cargo:warning=(not a warning) Building BPF {} program", + std::env::var("CARGO_PKG_NAME").unwrap() + ); + if !Command::new("cargo") + .arg("build-bpf") + .status() + .expect("Failed to build bpf") + .success() + { + exit(1); + } + } +} diff --git a/associated-token-account/program/run-tests.sh b/associated-token-account/program/run-tests.sh new file mode 100755 index 00000000..37b58a97 --- /dev/null +++ b/associated-token-account/program/run-tests.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -ex +cd "$(dirname "$0")" +cargo clippy +cargo build +cargo build-bpf + +if [[ $1 = -v ]]; then + export RUST_LOG=solana=debug +fi + +bpf=1 cargo test +# TODO: bpf=0 not supported until native CPI rework in the monorepo completes +#bpf=0 cargo test diff --git a/associated-token-account/program/src/entrypoint.rs b/associated-token-account/program/src/entrypoint.rs new file mode 100644 index 00000000..eb1eeb6a --- /dev/null +++ b/associated-token-account/program/src/entrypoint.rs @@ -0,0 +1,16 @@ +//! Program entrypoint + +#![cfg(all(target_arch = "bpf", not(feature = "exclude_entrypoint")))] + +use solana_program::{ + account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, +}; + +entrypoint!(process_instruction); +fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + crate::processor::process_instruction(program_id, accounts, instruction_data) +} diff --git a/associated-token-account/program/src/lib.rs b/associated-token-account/program/src/lib.rs new file mode 100644 index 00000000..ce67c738 --- /dev/null +++ b/associated-token-account/program/src/lib.rs @@ -0,0 +1,75 @@ +//! Convention for associating token accounts with a primary account (such as a user wallet) +#![deny(missing_docs)] +#![forbid(unsafe_code)] + +mod entrypoint; +pub mod processor; + +// Export current sdk types for downstream users building with a different sdk version +pub use solana_program; +use solana_program::{ + instruction::{AccountMeta, Instruction}, + program_pack::Pack, + pubkey::Pubkey, + sysvar, +}; + +solana_program::declare_id!("3medvrcM8s3UnkoYqqV3RAURii1ysuT5oD7t8nmfgJmj"); + +pub(crate) fn get_associated_token_address_and_bump_seed( + wallet_address: &Pubkey, + spl_token_mint_address: &Pubkey, + program_id: &Pubkey, +) -> (Pubkey, u8) { + Pubkey::find_program_address( + &[ + &wallet_address.to_bytes(), + &spl_token::id().to_bytes(), + &spl_token_mint_address.to_bytes(), + ], + program_id, + ) +} + +/// Derives the associated SPL token address for the given wallet address and SPL Token mint +pub fn get_associated_token_address( + wallet_address: &Pubkey, + spl_token_mint_address: &Pubkey, +) -> Pubkey { + get_associated_token_address_and_bump_seed(&wallet_address, &spl_token_mint_address, &id()).0 +} + +/// Create an associated token account for a wallet address +/// +/// Accounts expected by this instruction: +/// +/// 0. `[writeable,signer]` Funding account (must be a system account) +/// 1. `[writeable]` Associated token account address +/// 2. `[]` Wallet address for the new associated token account +/// 3. `[]` The SPL token mint for the associated token account +/// 4. `[]` System program +/// 4. `[]` SPL Token program +/// 5. `[]` Rent sysvar +/// +pub fn create_associated_token_account( + funding_address: &Pubkey, + wallet_address: &Pubkey, + spl_token_mint_address: &Pubkey, +) -> Instruction { + let associated_account_address = + get_associated_token_address(wallet_address, spl_token_mint_address); + + Instruction { + program_id: id(), + accounts: vec![ + AccountMeta::new(*funding_address, true), + AccountMeta::new(associated_account_address, false), + AccountMeta::new_readonly(*wallet_address, false), + AccountMeta::new_readonly(*spl_token_mint_address, false), + AccountMeta::new_readonly(solana_program::system_program::id(), false), + AccountMeta::new_readonly(spl_token::id(), false), + AccountMeta::new_readonly(sysvar::rent::id(), false), + ], + data: vec![], + } +} diff --git a/associated-token-account/program/src/processor.rs b/associated-token-account/program/src/processor.rs new file mode 100644 index 00000000..aebb5999 --- /dev/null +++ b/associated-token-account/program/src/processor.rs @@ -0,0 +1,113 @@ +//! Program state processor + +use crate::*; +use solana_program::{ + account_info::{next_account_info, AccountInfo}, + entrypoint::ProgramResult, + info, + log::sol_log_compute_units, + program::{invoke, invoke_signed}, + program_error::ProgramError, + pubkey::Pubkey, + rent::Rent, + system_instruction, + sysvar::Sysvar, +}; + +/// Instruction processor +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + _input: &[u8], +) -> ProgramResult { + let account_info_iter = &mut accounts.iter(); + + let funder_info = next_account_info(account_info_iter)?; + let associated_token_account_info = next_account_info(account_info_iter)?; + let wallet_account_info = next_account_info(account_info_iter)?; + let spl_token_mint_info = next_account_info(account_info_iter)?; + let system_program_info = next_account_info(account_info_iter)?; + let spl_token_program_info = next_account_info(account_info_iter)?; + let rent_sysvar_info = next_account_info(account_info_iter)?; + + let (associated_token_address, bump_seed) = get_associated_token_address_and_bump_seed( + &wallet_account_info.key, + &spl_token_mint_info.key, + program_id, + ); + if associated_token_address != *associated_token_account_info.key { + info!("Error: Associated address does not match seed derivation"); + return Err(ProgramError::InvalidSeeds); + } + + let associated_token_account_signer_seeds: &[&[_]] = &[ + &wallet_account_info.key.to_bytes(), + &spl_token::id().to_bytes(), + &spl_token_mint_info.key.to_bytes(), + &[bump_seed], + ]; + + sol_log_compute_units(); + + // Fund the associated token account with the minimum balance to be rent exempt + let rent = &Rent::from_account_info(rent_sysvar_info)?; + let required_lamports = rent + .minimum_balance(spl_token::state::Account::LEN) + .max(1) + .saturating_sub(associated_token_account_info.lamports()); + + if required_lamports > 0 { + invoke( + &system_instruction::transfer( + &funder_info.key, + associated_token_account_info.key, + required_lamports, + ), + &[ + funder_info.clone(), + associated_token_account_info.clone(), + system_program_info.clone(), + ], + )?; + } + + // Allocate space for the associated token account + invoke_signed( + &system_instruction::allocate( + associated_token_account_info.key, + spl_token::state::Account::LEN as u64, + ), + &[ + associated_token_account_info.clone(), + system_program_info.clone(), + ], + &[&associated_token_account_signer_seeds], + )?; + + // Assign the associated token account to the SPL Token program + invoke_signed( + &system_instruction::assign(associated_token_account_info.key, &spl_token::id()), + &[ + associated_token_account_info.clone(), + system_program_info.clone(), + ], + &[&associated_token_account_signer_seeds], + )?; + + // Initialize the associated token account + invoke( + &spl_token::instruction::initialize_account( + &spl_token::id(), + associated_token_account_info.key, + spl_token_mint_info.key, + wallet_account_info.key, + )?, + &[ + associated_token_account_info.clone(), + spl_token_mint_info.clone(), + wallet_account_info.clone(), + rent_sysvar_info.clone(), + spl_token_program_info.clone(), + ], + ) +} diff --git a/associated-token-account/program/tests/fixtures/token-mint-data.bin b/associated-token-account/program/tests/fixtures/token-mint-data.bin new file mode 100644 index 00000000..4a48512c Binary files /dev/null and b/associated-token-account/program/tests/fixtures/token-mint-data.bin differ diff --git a/associated-token-account/program/tests/functional.rs b/associated-token-account/program/tests/functional.rs new file mode 100644 index 00000000..15a37c0c --- /dev/null +++ b/associated-token-account/program/tests/functional.rs @@ -0,0 +1,251 @@ +use solana_program::{ + instruction::*, program_pack::Pack, pubkey::Pubkey, system_instruction, sysvar::rent::Rent, +}; +use solana_program_test::*; +use solana_sdk::{ + signature::Signer, + transaction::{Transaction, TransactionError}, +}; +use spl_associated_token_account::*; + +fn program_test(token_mint_address: Pubkey) -> ProgramTest { + let mut pc = ProgramTest::new( + "spl_associated_token_account", + id(), + // TODO: BPF only until native CPI rework in the monorepo completes + None, //processor!(processor::process_instruction), + ); + + // Add Token program + pc.add_program( + "spl_token", + spl_token::id(), + processor!(spl_token::processor::Processor::process), + ); + + // Add a token mint account + // + // The account data was generated by running: + // $ solana account EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \ + // --output-file tests/fixtures/token-mint-data.bin + // + pc.add_account_with_file_data( + token_mint_address, + 1461600, + spl_token::id(), + "token-mint-data.bin", + ); + + // Dial down the BPF compute budget to detect if the program gets bloated in the future + pc.set_bpf_compute_max_units(50_000); + + pc +} + +#[tokio::test] +async fn test_associated_token_address() { + let wallet_address = Pubkey::new_unique(); + let token_mint_address = Pubkey::new_unique(); + let associated_token_address = + get_associated_token_address(&wallet_address, &token_mint_address); + + let (mut banks_client, payer, recent_blockhash) = + program_test(token_mint_address).start().await; + let rent = Rent::default(); // <-- TODO: get Rent from `ProgramTest` + let expected_token_account_balance = rent.minimum_balance(spl_token::state::Account::LEN); + + // Associated account does not exist + assert_eq!( + banks_client + .get_account(associated_token_address) + .await + .expect("get_account"), + None, + ); + + let mut transaction = Transaction::new_with_payer( + &[create_associated_token_account( + &payer.pubkey(), + &wallet_address, + &token_mint_address, + )], + Some(&payer.pubkey()), + ); + transaction.sign(&[&payer], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Associated account now exists + let associated_account = banks_client + .get_account(associated_token_address) + .await + .expect("get_account") + .expect("associated_account not none"); + assert_eq!( + associated_account.data.len(), + spl_token::state::Account::LEN + ); + assert_eq!(associated_account.owner, spl_token::id()); + assert_eq!(associated_account.lamports, expected_token_account_balance); +} + +#[tokio::test] +async fn test_create_with_a_lamport() { + let wallet_address = Pubkey::new_unique(); + let token_mint_address = Pubkey::new_unique(); + let associated_token_address = + get_associated_token_address(&wallet_address, &token_mint_address); + + let (mut banks_client, payer, recent_blockhash) = + program_test(token_mint_address).start().await; + let rent = Rent::default(); // <-- TOOD: get Rent from `ProgramTest` + let expected_token_account_balance = rent.minimum_balance(spl_token::state::Account::LEN); + + // Transfer 1 lamport into `associated_token_address` before creating it + let mut transaction = Transaction::new_with_payer( + &[system_instruction::transfer( + &payer.pubkey(), + &associated_token_address, + 1, + )], + Some(&payer.pubkey()), + ); + transaction.sign(&[&payer], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + assert_eq!( + banks_client + .get_balance(associated_token_address) + .await + .unwrap(), + 1 + ); + + // Check that the program adds the extra lamports + let mut transaction = Transaction::new_with_payer( + &[create_associated_token_account( + &payer.pubkey(), + &wallet_address, + &token_mint_address, + )], + Some(&payer.pubkey()), + ); + transaction.sign(&[&payer], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + assert_eq!( + banks_client + .get_balance(associated_token_address) + .await + .unwrap(), + expected_token_account_balance, + ); +} + +#[tokio::test] +async fn test_create_with_excess_lamports() { + let wallet_address = Pubkey::new_unique(); + let token_mint_address = Pubkey::new_unique(); + let associated_token_address = + get_associated_token_address(&wallet_address, &token_mint_address); + + let (mut banks_client, payer, recent_blockhash) = + program_test(token_mint_address).start().await; + let rent = Rent::default(); // <-- TOOD: get Rent from `ProgramTest` + let expected_token_account_balance = rent.minimum_balance(spl_token::state::Account::LEN); + + // Transfer 1 lamport into `associated_token_address` before creating it + let mut transaction = Transaction::new_with_payer( + &[system_instruction::transfer( + &payer.pubkey(), + &associated_token_address, + expected_token_account_balance + 1, + )], + Some(&payer.pubkey()), + ); + transaction.sign(&[&payer], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + assert_eq!( + banks_client + .get_balance(associated_token_address) + .await + .unwrap(), + expected_token_account_balance + 1 + ); + + // Check that the program doesn't add any lamports + let mut transaction = Transaction::new_with_payer( + &[create_associated_token_account( + &payer.pubkey(), + &wallet_address, + &token_mint_address, + )], + Some(&payer.pubkey()), + ); + transaction.sign(&[&payer], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + assert_eq!( + banks_client + .get_balance(associated_token_address) + .await + .unwrap(), + expected_token_account_balance + 1 + ); +} + +#[tokio::test] +async fn test_create_account_mismatch() { + let wallet_address = Pubkey::new_unique(); + let token_mint_address = Pubkey::new_unique(); + let _associated_token_address = + get_associated_token_address(&wallet_address, &token_mint_address); + + let (mut banks_client, payer, recent_blockhash) = + program_test(token_mint_address).start().await; + + let mut instruction = + create_associated_token_account(&payer.pubkey(), &wallet_address, &token_mint_address); + instruction.accounts[1] = AccountMeta::new(Pubkey::default(), false); // <-- Invalid associated_account_address + + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], recent_blockhash); + assert_eq!( + banks_client + .process_transaction(transaction) + .await + .unwrap_err() + .unwrap(), + TransactionError::InstructionError(0, InstructionError::InvalidSeeds) + ); + + let mut instruction = + create_associated_token_account(&payer.pubkey(), &wallet_address, &token_mint_address); + instruction.accounts[2] = AccountMeta::new(Pubkey::default(), false); // <-- Invalid wallet_address + + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], recent_blockhash); + assert_eq!( + banks_client + .process_transaction(transaction) + .await + .unwrap_err() + .unwrap(), + TransactionError::InstructionError(0, InstructionError::InvalidSeeds) + ); + + let mut instruction = + create_associated_token_account(&payer.pubkey(), &wallet_address, &token_mint_address); + instruction.accounts[3] = AccountMeta::new(Pubkey::default(), false); // <-- Invalid token_mint_address + + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], recent_blockhash); + assert_eq!( + banks_client + .process_transaction(transaction) + .await + .unwrap_err() + .unwrap(), + TransactionError::InstructionError(0, InstructionError::InvalidSeeds) + ); +}