processor.rs 232 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012
  1. //! Program state processor
  2. use crate::{
  3. amount_to_ui_amount_string_trimmed,
  4. error::TokenError,
  5. instruction::{is_valid_signer_index, AuthorityType, TokenInstruction, MAX_SIGNERS},
  6. state::{Account, AccountState, Mint, Multisig},
  7. try_ui_amount_into_amount,
  8. };
  9. use solana_program::{
  10. account_info::{next_account_info, AccountInfo},
  11. entrypoint::ProgramResult,
  12. msg,
  13. program::set_return_data,
  14. program_error::ProgramError,
  15. program_memory::sol_memcmp,
  16. program_option::COption,
  17. program_pack::{IsInitialized, Pack},
  18. pubkey::{Pubkey, PUBKEY_BYTES},
  19. system_program,
  20. sysvar::{rent::Rent, Sysvar},
  21. };
  22. /// Program state handler.
  23. pub struct Processor {}
  24. impl Processor {
  25. fn _process_initialize_mint(
  26. accounts: &[AccountInfo],
  27. decimals: u8,
  28. mint_authority: Pubkey,
  29. freeze_authority: COption<Pubkey>,
  30. rent_sysvar_account: bool,
  31. ) -> ProgramResult {
  32. let account_info_iter = &mut accounts.iter();
  33. let mint_info = next_account_info(account_info_iter)?;
  34. let mint_data_len = mint_info.data_len();
  35. let rent = if rent_sysvar_account {
  36. Rent::from_account_info(next_account_info(account_info_iter)?)?
  37. } else {
  38. Rent::get()?
  39. };
  40. let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow())?;
  41. if mint.is_initialized {
  42. return Err(TokenError::AlreadyInUse.into());
  43. }
  44. if !rent.is_exempt(mint_info.lamports(), mint_data_len) {
  45. return Err(TokenError::NotRentExempt.into());
  46. }
  47. mint.mint_authority = COption::Some(mint_authority);
  48. mint.decimals = decimals;
  49. mint.is_initialized = true;
  50. mint.freeze_authority = freeze_authority;
  51. Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
  52. Ok(())
  53. }
  54. /// Processes an [InitializeMint](enum.TokenInstruction.html) instruction.
  55. pub fn process_initialize_mint(
  56. accounts: &[AccountInfo],
  57. decimals: u8,
  58. mint_authority: Pubkey,
  59. freeze_authority: COption<Pubkey>,
  60. ) -> ProgramResult {
  61. Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, true)
  62. }
  63. /// Processes an [InitializeMint2](enum.TokenInstruction.html) instruction.
  64. pub fn process_initialize_mint2(
  65. accounts: &[AccountInfo],
  66. decimals: u8,
  67. mint_authority: Pubkey,
  68. freeze_authority: COption<Pubkey>,
  69. ) -> ProgramResult {
  70. Self::_process_initialize_mint(accounts, decimals, mint_authority, freeze_authority, false)
  71. }
  72. fn _process_initialize_account(
  73. program_id: &Pubkey,
  74. accounts: &[AccountInfo],
  75. owner: Option<&Pubkey>,
  76. rent_sysvar_account: bool,
  77. ) -> ProgramResult {
  78. let account_info_iter = &mut accounts.iter();
  79. let new_account_info = next_account_info(account_info_iter)?;
  80. let mint_info = next_account_info(account_info_iter)?;
  81. let owner = if let Some(owner) = owner {
  82. owner
  83. } else {
  84. next_account_info(account_info_iter)?.key
  85. };
  86. let new_account_info_data_len = new_account_info.data_len();
  87. let rent = if rent_sysvar_account {
  88. Rent::from_account_info(next_account_info(account_info_iter)?)?
  89. } else {
  90. Rent::get()?
  91. };
  92. let mut account = Account::unpack_unchecked(&new_account_info.data.borrow())?;
  93. if account.is_initialized() {
  94. return Err(TokenError::AlreadyInUse.into());
  95. }
  96. if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) {
  97. return Err(TokenError::NotRentExempt.into());
  98. }
  99. let is_native_mint = Self::cmp_pubkeys(mint_info.key, &crate::native_mint::id());
  100. if !is_native_mint {
  101. Self::check_account_owner(program_id, mint_info)?;
  102. let _ = Mint::unpack(&mint_info.data.borrow_mut())
  103. .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
  104. }
  105. account.mint = *mint_info.key;
  106. account.owner = *owner;
  107. account.close_authority = COption::None;
  108. account.delegate = COption::None;
  109. account.delegated_amount = 0;
  110. account.state = AccountState::Initialized;
  111. if is_native_mint {
  112. let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len);
  113. account.is_native = COption::Some(rent_exempt_reserve);
  114. account.amount = new_account_info
  115. .lamports()
  116. .checked_sub(rent_exempt_reserve)
  117. .ok_or(TokenError::Overflow)?;
  118. } else {
  119. account.is_native = COption::None;
  120. account.amount = 0;
  121. };
  122. Account::pack(account, &mut new_account_info.data.borrow_mut())?;
  123. Ok(())
  124. }
  125. /// Processes an [InitializeAccount](enum.TokenInstruction.html) instruction.
  126. pub fn process_initialize_account(
  127. program_id: &Pubkey,
  128. accounts: &[AccountInfo],
  129. ) -> ProgramResult {
  130. Self::_process_initialize_account(program_id, accounts, None, true)
  131. }
  132. /// Processes an [InitializeAccount2](enum.TokenInstruction.html) instruction.
  133. pub fn process_initialize_account2(
  134. program_id: &Pubkey,
  135. accounts: &[AccountInfo],
  136. owner: Pubkey,
  137. ) -> ProgramResult {
  138. Self::_process_initialize_account(program_id, accounts, Some(&owner), true)
  139. }
  140. /// Processes an [InitializeAccount3](enum.TokenInstruction.html) instruction.
  141. pub fn process_initialize_account3(
  142. program_id: &Pubkey,
  143. accounts: &[AccountInfo],
  144. owner: Pubkey,
  145. ) -> ProgramResult {
  146. Self::_process_initialize_account(program_id, accounts, Some(&owner), false)
  147. }
  148. fn _process_initialize_multisig(
  149. accounts: &[AccountInfo],
  150. m: u8,
  151. rent_sysvar_account: bool,
  152. ) -> ProgramResult {
  153. let account_info_iter = &mut accounts.iter();
  154. let multisig_info = next_account_info(account_info_iter)?;
  155. let multisig_info_data_len = multisig_info.data_len();
  156. let rent = if rent_sysvar_account {
  157. Rent::from_account_info(next_account_info(account_info_iter)?)?
  158. } else {
  159. Rent::get()?
  160. };
  161. let mut multisig = Multisig::unpack_unchecked(&multisig_info.data.borrow())?;
  162. if multisig.is_initialized {
  163. return Err(TokenError::AlreadyInUse.into());
  164. }
  165. if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) {
  166. return Err(TokenError::NotRentExempt.into());
  167. }
  168. let signer_infos = account_info_iter.as_slice();
  169. multisig.m = m;
  170. multisig.n = signer_infos.len() as u8;
  171. if !is_valid_signer_index(multisig.n as usize) {
  172. return Err(TokenError::InvalidNumberOfProvidedSigners.into());
  173. }
  174. if !is_valid_signer_index(multisig.m as usize) {
  175. return Err(TokenError::InvalidNumberOfRequiredSigners.into());
  176. }
  177. for (i, signer_info) in signer_infos.iter().enumerate() {
  178. multisig.signers[i] = *signer_info.key;
  179. }
  180. multisig.is_initialized = true;
  181. Multisig::pack(multisig, &mut multisig_info.data.borrow_mut())?;
  182. Ok(())
  183. }
  184. /// Processes a [InitializeMultisig](enum.TokenInstruction.html) instruction.
  185. pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
  186. Self::_process_initialize_multisig(accounts, m, true)
  187. }
  188. /// Processes a [InitializeMultisig2](enum.TokenInstruction.html) instruction.
  189. pub fn process_initialize_multisig2(accounts: &[AccountInfo], m: u8) -> ProgramResult {
  190. Self::_process_initialize_multisig(accounts, m, false)
  191. }
  192. /// Processes a [Transfer](enum.TokenInstruction.html) instruction.
  193. pub fn process_transfer(
  194. program_id: &Pubkey,
  195. accounts: &[AccountInfo],
  196. amount: u64,
  197. expected_decimals: Option<u8>,
  198. ) -> ProgramResult {
  199. let account_info_iter = &mut accounts.iter();
  200. let source_account_info = next_account_info(account_info_iter)?;
  201. let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
  202. Some((next_account_info(account_info_iter)?, expected_decimals))
  203. } else {
  204. None
  205. };
  206. let destination_account_info = next_account_info(account_info_iter)?;
  207. let authority_info = next_account_info(account_info_iter)?;
  208. let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
  209. let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
  210. if source_account.is_frozen() || destination_account.is_frozen() {
  211. return Err(TokenError::AccountFrozen.into());
  212. }
  213. if source_account.amount < amount {
  214. return Err(TokenError::InsufficientFunds.into());
  215. }
  216. if !Self::cmp_pubkeys(&source_account.mint, &destination_account.mint) {
  217. return Err(TokenError::MintMismatch.into());
  218. }
  219. if let Some((mint_info, expected_decimals)) = expected_mint_info {
  220. if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
  221. return Err(TokenError::MintMismatch.into());
  222. }
  223. let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
  224. if expected_decimals != mint.decimals {
  225. return Err(TokenError::MintDecimalsMismatch.into());
  226. }
  227. }
  228. let self_transfer =
  229. Self::cmp_pubkeys(source_account_info.key, destination_account_info.key);
  230. match source_account.delegate {
  231. COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
  232. Self::validate_owner(
  233. program_id,
  234. delegate,
  235. authority_info,
  236. account_info_iter.as_slice(),
  237. )?;
  238. if source_account.delegated_amount < amount {
  239. return Err(TokenError::InsufficientFunds.into());
  240. }
  241. if !self_transfer {
  242. source_account.delegated_amount = source_account
  243. .delegated_amount
  244. .checked_sub(amount)
  245. .ok_or(TokenError::Overflow)?;
  246. if source_account.delegated_amount == 0 {
  247. source_account.delegate = COption::None;
  248. }
  249. }
  250. }
  251. _ => Self::validate_owner(
  252. program_id,
  253. &source_account.owner,
  254. authority_info,
  255. account_info_iter.as_slice(),
  256. )?,
  257. };
  258. if self_transfer || amount == 0 {
  259. Self::check_account_owner(program_id, source_account_info)?;
  260. Self::check_account_owner(program_id, destination_account_info)?;
  261. }
  262. // This check MUST occur just before the amounts are manipulated
  263. // to ensure self-transfers are fully validated
  264. if self_transfer {
  265. return Ok(());
  266. }
  267. source_account.amount = source_account
  268. .amount
  269. .checked_sub(amount)
  270. .ok_or(TokenError::Overflow)?;
  271. destination_account.amount = destination_account
  272. .amount
  273. .checked_add(amount)
  274. .ok_or(TokenError::Overflow)?;
  275. if source_account.is_native() {
  276. let source_starting_lamports = source_account_info.lamports();
  277. **source_account_info.lamports.borrow_mut() = source_starting_lamports
  278. .checked_sub(amount)
  279. .ok_or(TokenError::Overflow)?;
  280. let destination_starting_lamports = destination_account_info.lamports();
  281. **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
  282. .checked_add(amount)
  283. .ok_or(TokenError::Overflow)?;
  284. }
  285. Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
  286. Account::pack(
  287. destination_account,
  288. &mut destination_account_info.data.borrow_mut(),
  289. )?;
  290. Ok(())
  291. }
  292. /// Processes an [Approve](enum.TokenInstruction.html) instruction.
  293. pub fn process_approve(
  294. program_id: &Pubkey,
  295. accounts: &[AccountInfo],
  296. amount: u64,
  297. expected_decimals: Option<u8>,
  298. ) -> ProgramResult {
  299. let account_info_iter = &mut accounts.iter();
  300. let source_account_info = next_account_info(account_info_iter)?;
  301. let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
  302. Some((next_account_info(account_info_iter)?, expected_decimals))
  303. } else {
  304. None
  305. };
  306. let delegate_info = next_account_info(account_info_iter)?;
  307. let owner_info = next_account_info(account_info_iter)?;
  308. let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
  309. if source_account.is_frozen() {
  310. return Err(TokenError::AccountFrozen.into());
  311. }
  312. if let Some((mint_info, expected_decimals)) = expected_mint_info {
  313. if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
  314. return Err(TokenError::MintMismatch.into());
  315. }
  316. let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
  317. if expected_decimals != mint.decimals {
  318. return Err(TokenError::MintDecimalsMismatch.into());
  319. }
  320. }
  321. Self::validate_owner(
  322. program_id,
  323. &source_account.owner,
  324. owner_info,
  325. account_info_iter.as_slice(),
  326. )?;
  327. source_account.delegate = COption::Some(*delegate_info.key);
  328. source_account.delegated_amount = amount;
  329. Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
  330. Ok(())
  331. }
  332. /// Processes an [Revoke](enum.TokenInstruction.html) instruction.
  333. pub fn process_revoke(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
  334. let account_info_iter = &mut accounts.iter();
  335. let source_account_info = next_account_info(account_info_iter)?;
  336. let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
  337. let owner_info = next_account_info(account_info_iter)?;
  338. if source_account.is_frozen() {
  339. return Err(TokenError::AccountFrozen.into());
  340. }
  341. Self::validate_owner(
  342. program_id,
  343. &source_account.owner,
  344. owner_info,
  345. account_info_iter.as_slice(),
  346. )?;
  347. source_account.delegate = COption::None;
  348. source_account.delegated_amount = 0;
  349. Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
  350. Ok(())
  351. }
  352. /// Processes a [SetAuthority](enum.TokenInstruction.html) instruction.
  353. pub fn process_set_authority(
  354. program_id: &Pubkey,
  355. accounts: &[AccountInfo],
  356. authority_type: AuthorityType,
  357. new_authority: COption<Pubkey>,
  358. ) -> ProgramResult {
  359. let account_info_iter = &mut accounts.iter();
  360. let account_info = next_account_info(account_info_iter)?;
  361. let authority_info = next_account_info(account_info_iter)?;
  362. if account_info.data_len() == Account::get_packed_len() {
  363. let mut account = Account::unpack(&account_info.data.borrow())?;
  364. if account.is_frozen() {
  365. return Err(TokenError::AccountFrozen.into());
  366. }
  367. match authority_type {
  368. AuthorityType::AccountOwner => {
  369. Self::validate_owner(
  370. program_id,
  371. &account.owner,
  372. authority_info,
  373. account_info_iter.as_slice(),
  374. )?;
  375. if let COption::Some(authority) = new_authority {
  376. account.owner = authority;
  377. } else {
  378. return Err(TokenError::InvalidInstruction.into());
  379. }
  380. account.delegate = COption::None;
  381. account.delegated_amount = 0;
  382. if account.is_native() {
  383. account.close_authority = COption::None;
  384. }
  385. }
  386. AuthorityType::CloseAccount => {
  387. let authority = account.close_authority.unwrap_or(account.owner);
  388. Self::validate_owner(
  389. program_id,
  390. &authority,
  391. authority_info,
  392. account_info_iter.as_slice(),
  393. )?;
  394. account.close_authority = new_authority;
  395. }
  396. _ => {
  397. return Err(TokenError::AuthorityTypeNotSupported.into());
  398. }
  399. }
  400. Account::pack(account, &mut account_info.data.borrow_mut())?;
  401. } else if account_info.data_len() == Mint::get_packed_len() {
  402. let mut mint = Mint::unpack(&account_info.data.borrow())?;
  403. match authority_type {
  404. AuthorityType::MintTokens => {
  405. // Once a mint's supply is fixed, it cannot be undone by setting a new
  406. // mint_authority
  407. let mint_authority = mint
  408. .mint_authority
  409. .ok_or(Into::<ProgramError>::into(TokenError::FixedSupply))?;
  410. Self::validate_owner(
  411. program_id,
  412. &mint_authority,
  413. authority_info,
  414. account_info_iter.as_slice(),
  415. )?;
  416. mint.mint_authority = new_authority;
  417. }
  418. AuthorityType::FreezeAccount => {
  419. // Once a mint's freeze authority is disabled, it cannot be re-enabled by
  420. // setting a new freeze_authority
  421. let freeze_authority = mint
  422. .freeze_authority
  423. .ok_or(Into::<ProgramError>::into(TokenError::MintCannotFreeze))?;
  424. Self::validate_owner(
  425. program_id,
  426. &freeze_authority,
  427. authority_info,
  428. account_info_iter.as_slice(),
  429. )?;
  430. mint.freeze_authority = new_authority;
  431. }
  432. _ => {
  433. return Err(TokenError::AuthorityTypeNotSupported.into());
  434. }
  435. }
  436. Mint::pack(mint, &mut account_info.data.borrow_mut())?;
  437. } else {
  438. return Err(ProgramError::InvalidArgument);
  439. }
  440. Ok(())
  441. }
  442. /// Processes a [MintTo](enum.TokenInstruction.html) instruction.
  443. pub fn process_mint_to(
  444. program_id: &Pubkey,
  445. accounts: &[AccountInfo],
  446. amount: u64,
  447. expected_decimals: Option<u8>,
  448. ) -> ProgramResult {
  449. let account_info_iter = &mut accounts.iter();
  450. let mint_info = next_account_info(account_info_iter)?;
  451. let destination_account_info = next_account_info(account_info_iter)?;
  452. let owner_info = next_account_info(account_info_iter)?;
  453. let mut destination_account = Account::unpack(&destination_account_info.data.borrow())?;
  454. if destination_account.is_frozen() {
  455. return Err(TokenError::AccountFrozen.into());
  456. }
  457. if destination_account.is_native() {
  458. return Err(TokenError::NativeNotSupported.into());
  459. }
  460. if !Self::cmp_pubkeys(mint_info.key, &destination_account.mint) {
  461. return Err(TokenError::MintMismatch.into());
  462. }
  463. let mut mint = Mint::unpack(&mint_info.data.borrow())?;
  464. if let Some(expected_decimals) = expected_decimals {
  465. if expected_decimals != mint.decimals {
  466. return Err(TokenError::MintDecimalsMismatch.into());
  467. }
  468. }
  469. match mint.mint_authority {
  470. COption::Some(mint_authority) => Self::validate_owner(
  471. program_id,
  472. &mint_authority,
  473. owner_info,
  474. account_info_iter.as_slice(),
  475. )?,
  476. COption::None => return Err(TokenError::FixedSupply.into()),
  477. }
  478. if amount == 0 {
  479. Self::check_account_owner(program_id, mint_info)?;
  480. Self::check_account_owner(program_id, destination_account_info)?;
  481. }
  482. destination_account.amount = destination_account
  483. .amount
  484. .checked_add(amount)
  485. .ok_or(TokenError::Overflow)?;
  486. mint.supply = mint
  487. .supply
  488. .checked_add(amount)
  489. .ok_or(TokenError::Overflow)?;
  490. Account::pack(
  491. destination_account,
  492. &mut destination_account_info.data.borrow_mut(),
  493. )?;
  494. Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
  495. Ok(())
  496. }
  497. /// Processes a [Burn](enum.TokenInstruction.html) instruction.
  498. pub fn process_burn(
  499. program_id: &Pubkey,
  500. accounts: &[AccountInfo],
  501. amount: u64,
  502. expected_decimals: Option<u8>,
  503. ) -> ProgramResult {
  504. let account_info_iter = &mut accounts.iter();
  505. let source_account_info = next_account_info(account_info_iter)?;
  506. let mint_info = next_account_info(account_info_iter)?;
  507. let authority_info = next_account_info(account_info_iter)?;
  508. let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
  509. let mut mint = Mint::unpack(&mint_info.data.borrow())?;
  510. if source_account.is_frozen() {
  511. return Err(TokenError::AccountFrozen.into());
  512. }
  513. if source_account.is_native() {
  514. return Err(TokenError::NativeNotSupported.into());
  515. }
  516. if source_account.amount < amount {
  517. return Err(TokenError::InsufficientFunds.into());
  518. }
  519. if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
  520. return Err(TokenError::MintMismatch.into());
  521. }
  522. if let Some(expected_decimals) = expected_decimals {
  523. if expected_decimals != mint.decimals {
  524. return Err(TokenError::MintDecimalsMismatch.into());
  525. }
  526. }
  527. if !source_account.is_owned_by_system_program_or_incinerator() {
  528. match source_account.delegate {
  529. COption::Some(ref delegate) if Self::cmp_pubkeys(authority_info.key, delegate) => {
  530. Self::validate_owner(
  531. program_id,
  532. delegate,
  533. authority_info,
  534. account_info_iter.as_slice(),
  535. )?;
  536. if source_account.delegated_amount < amount {
  537. return Err(TokenError::InsufficientFunds.into());
  538. }
  539. source_account.delegated_amount = source_account
  540. .delegated_amount
  541. .checked_sub(amount)
  542. .ok_or(TokenError::Overflow)?;
  543. if source_account.delegated_amount == 0 {
  544. source_account.delegate = COption::None;
  545. }
  546. }
  547. _ => Self::validate_owner(
  548. program_id,
  549. &source_account.owner,
  550. authority_info,
  551. account_info_iter.as_slice(),
  552. )?,
  553. }
  554. }
  555. if amount == 0 {
  556. Self::check_account_owner(program_id, source_account_info)?;
  557. Self::check_account_owner(program_id, mint_info)?;
  558. }
  559. source_account.amount = source_account
  560. .amount
  561. .checked_sub(amount)
  562. .ok_or(TokenError::Overflow)?;
  563. mint.supply = mint
  564. .supply
  565. .checked_sub(amount)
  566. .ok_or(TokenError::Overflow)?;
  567. Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
  568. Mint::pack(mint, &mut mint_info.data.borrow_mut())?;
  569. Ok(())
  570. }
  571. /// Processes a [CloseAccount](enum.TokenInstruction.html) instruction.
  572. pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
  573. let account_info_iter = &mut accounts.iter();
  574. let source_account_info = next_account_info(account_info_iter)?;
  575. let destination_account_info = next_account_info(account_info_iter)?;
  576. let authority_info = next_account_info(account_info_iter)?;
  577. if Self::cmp_pubkeys(source_account_info.key, destination_account_info.key) {
  578. return Err(ProgramError::InvalidAccountData);
  579. }
  580. let source_account = Account::unpack(&source_account_info.data.borrow())?;
  581. if !source_account.is_native() && source_account.amount != 0 {
  582. return Err(TokenError::NonNativeHasBalance.into());
  583. }
  584. let authority = source_account
  585. .close_authority
  586. .unwrap_or(source_account.owner);
  587. if !source_account.is_owned_by_system_program_or_incinerator() {
  588. Self::validate_owner(
  589. program_id,
  590. &authority,
  591. authority_info,
  592. account_info_iter.as_slice(),
  593. )?;
  594. } else if !solana_program::incinerator::check_id(destination_account_info.key) {
  595. return Err(ProgramError::InvalidAccountData);
  596. }
  597. let destination_starting_lamports = destination_account_info.lamports();
  598. **destination_account_info.lamports.borrow_mut() = destination_starting_lamports
  599. .checked_add(source_account_info.lamports())
  600. .ok_or(TokenError::Overflow)?;
  601. **source_account_info.lamports.borrow_mut() = 0;
  602. delete_account(source_account_info)?;
  603. Ok(())
  604. }
  605. /// Processes a [FreezeAccount](enum.TokenInstruction.html) or a
  606. /// [ThawAccount](enum.TokenInstruction.html) instruction.
  607. pub fn process_toggle_freeze_account(
  608. program_id: &Pubkey,
  609. accounts: &[AccountInfo],
  610. freeze: bool,
  611. ) -> ProgramResult {
  612. let account_info_iter = &mut accounts.iter();
  613. let source_account_info = next_account_info(account_info_iter)?;
  614. let mint_info = next_account_info(account_info_iter)?;
  615. let authority_info = next_account_info(account_info_iter)?;
  616. let mut source_account = Account::unpack(&source_account_info.data.borrow())?;
  617. if freeze && source_account.is_frozen() || !freeze && !source_account.is_frozen() {
  618. return Err(TokenError::InvalidState.into());
  619. }
  620. if source_account.is_native() {
  621. return Err(TokenError::NativeNotSupported.into());
  622. }
  623. if !Self::cmp_pubkeys(mint_info.key, &source_account.mint) {
  624. return Err(TokenError::MintMismatch.into());
  625. }
  626. let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
  627. match mint.freeze_authority {
  628. COption::Some(authority) => Self::validate_owner(
  629. program_id,
  630. &authority,
  631. authority_info,
  632. account_info_iter.as_slice(),
  633. ),
  634. COption::None => Err(TokenError::MintCannotFreeze.into()),
  635. }?;
  636. source_account.state = if freeze {
  637. AccountState::Frozen
  638. } else {
  639. AccountState::Initialized
  640. };
  641. Account::pack(source_account, &mut source_account_info.data.borrow_mut())?;
  642. Ok(())
  643. }
  644. /// Processes a [SyncNative](enum.TokenInstruction.html) instruction
  645. pub fn process_sync_native(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
  646. let account_info_iter = &mut accounts.iter();
  647. let native_account_info = next_account_info(account_info_iter)?;
  648. Self::check_account_owner(program_id, native_account_info)?;
  649. let mut native_account = Account::unpack(&native_account_info.data.borrow())?;
  650. if let COption::Some(rent_exempt_reserve) = native_account.is_native {
  651. let new_amount = native_account_info
  652. .lamports()
  653. .checked_sub(rent_exempt_reserve)
  654. .ok_or(TokenError::Overflow)?;
  655. if new_amount < native_account.amount {
  656. return Err(TokenError::InvalidState.into());
  657. }
  658. native_account.amount = new_amount;
  659. } else {
  660. return Err(TokenError::NonNativeNotSupported.into());
  661. }
  662. Account::pack(native_account, &mut native_account_info.data.borrow_mut())?;
  663. Ok(())
  664. }
  665. /// Processes a [GetAccountDataSize](enum.TokenInstruction.html) instruction
  666. pub fn process_get_account_data_size(
  667. program_id: &Pubkey,
  668. accounts: &[AccountInfo],
  669. ) -> ProgramResult {
  670. let account_info_iter = &mut accounts.iter();
  671. // make sure the mint is valid
  672. let mint_info = next_account_info(account_info_iter)?;
  673. Self::check_account_owner(program_id, mint_info)?;
  674. let _ = Mint::unpack(&mint_info.data.borrow())
  675. .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
  676. set_return_data(&Account::LEN.to_le_bytes());
  677. Ok(())
  678. }
  679. /// Processes an [InitializeImmutableOwner](enum.TokenInstruction.html) instruction
  680. pub fn process_initialize_immutable_owner(accounts: &[AccountInfo]) -> ProgramResult {
  681. let account_info_iter = &mut accounts.iter();
  682. let token_account_info = next_account_info(account_info_iter)?;
  683. let account = Account::unpack_unchecked(&token_account_info.data.borrow())?;
  684. if account.is_initialized() {
  685. return Err(TokenError::AlreadyInUse.into());
  686. }
  687. msg!("Please upgrade to SPL Token 2022 for immutable owner support");
  688. Ok(())
  689. }
  690. /// Processes an [AmountToUiAmount](enum.TokenInstruction.html) instruction
  691. pub fn process_amount_to_ui_amount(
  692. program_id: &Pubkey,
  693. accounts: &[AccountInfo],
  694. amount: u64,
  695. ) -> ProgramResult {
  696. let account_info_iter = &mut accounts.iter();
  697. let mint_info = next_account_info(account_info_iter)?;
  698. Self::check_account_owner(program_id, mint_info)?;
  699. let mint = Mint::unpack(&mint_info.data.borrow_mut())
  700. .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
  701. let ui_amount = amount_to_ui_amount_string_trimmed(amount, mint.decimals);
  702. set_return_data(&ui_amount.into_bytes());
  703. Ok(())
  704. }
  705. /// Processes an [AmountToUiAmount](enum.TokenInstruction.html) instruction
  706. pub fn process_ui_amount_to_amount(
  707. program_id: &Pubkey,
  708. accounts: &[AccountInfo],
  709. ui_amount: &str,
  710. ) -> ProgramResult {
  711. let account_info_iter = &mut accounts.iter();
  712. let mint_info = next_account_info(account_info_iter)?;
  713. Self::check_account_owner(program_id, mint_info)?;
  714. let mint = Mint::unpack(&mint_info.data.borrow_mut())
  715. .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
  716. let amount = try_ui_amount_into_amount(ui_amount.to_string(), mint.decimals)?;
  717. set_return_data(&amount.to_le_bytes());
  718. Ok(())
  719. }
  720. /// Processes an [Instruction](enum.Instruction.html).
  721. pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
  722. let instruction = TokenInstruction::unpack(input)?;
  723. match instruction {
  724. TokenInstruction::InitializeMint {
  725. decimals,
  726. mint_authority,
  727. freeze_authority,
  728. } => {
  729. msg!("Instruction: InitializeMint");
  730. Self::process_initialize_mint(accounts, decimals, mint_authority, freeze_authority)
  731. }
  732. TokenInstruction::InitializeMint2 {
  733. decimals,
  734. mint_authority,
  735. freeze_authority,
  736. } => {
  737. msg!("Instruction: InitializeMint2");
  738. Self::process_initialize_mint2(accounts, decimals, mint_authority, freeze_authority)
  739. }
  740. TokenInstruction::InitializeAccount => {
  741. msg!("Instruction: InitializeAccount");
  742. Self::process_initialize_account(program_id, accounts)
  743. }
  744. TokenInstruction::InitializeAccount2 { owner } => {
  745. msg!("Instruction: InitializeAccount2");
  746. Self::process_initialize_account2(program_id, accounts, owner)
  747. }
  748. TokenInstruction::InitializeAccount3 { owner } => {
  749. msg!("Instruction: InitializeAccount3");
  750. Self::process_initialize_account3(program_id, accounts, owner)
  751. }
  752. TokenInstruction::InitializeMultisig { m } => {
  753. msg!("Instruction: InitializeMultisig");
  754. Self::process_initialize_multisig(accounts, m)
  755. }
  756. TokenInstruction::InitializeMultisig2 { m } => {
  757. msg!("Instruction: InitializeMultisig2");
  758. Self::process_initialize_multisig2(accounts, m)
  759. }
  760. TokenInstruction::Transfer { amount } => {
  761. msg!("Instruction: Transfer");
  762. Self::process_transfer(program_id, accounts, amount, None)
  763. }
  764. TokenInstruction::Approve { amount } => {
  765. msg!("Instruction: Approve");
  766. Self::process_approve(program_id, accounts, amount, None)
  767. }
  768. TokenInstruction::Revoke => {
  769. msg!("Instruction: Revoke");
  770. Self::process_revoke(program_id, accounts)
  771. }
  772. TokenInstruction::SetAuthority {
  773. authority_type,
  774. new_authority,
  775. } => {
  776. msg!("Instruction: SetAuthority");
  777. Self::process_set_authority(program_id, accounts, authority_type, new_authority)
  778. }
  779. TokenInstruction::MintTo { amount } => {
  780. msg!("Instruction: MintTo");
  781. Self::process_mint_to(program_id, accounts, amount, None)
  782. }
  783. TokenInstruction::Burn { amount } => {
  784. msg!("Instruction: Burn");
  785. Self::process_burn(program_id, accounts, amount, None)
  786. }
  787. TokenInstruction::CloseAccount => {
  788. msg!("Instruction: CloseAccount");
  789. Self::process_close_account(program_id, accounts)
  790. }
  791. TokenInstruction::FreezeAccount => {
  792. msg!("Instruction: FreezeAccount");
  793. Self::process_toggle_freeze_account(program_id, accounts, true)
  794. }
  795. TokenInstruction::ThawAccount => {
  796. msg!("Instruction: ThawAccount");
  797. Self::process_toggle_freeze_account(program_id, accounts, false)
  798. }
  799. TokenInstruction::TransferChecked { amount, decimals } => {
  800. msg!("Instruction: TransferChecked");
  801. Self::process_transfer(program_id, accounts, amount, Some(decimals))
  802. }
  803. TokenInstruction::ApproveChecked { amount, decimals } => {
  804. msg!("Instruction: ApproveChecked");
  805. Self::process_approve(program_id, accounts, amount, Some(decimals))
  806. }
  807. TokenInstruction::MintToChecked { amount, decimals } => {
  808. msg!("Instruction: MintToChecked");
  809. Self::process_mint_to(program_id, accounts, amount, Some(decimals))
  810. }
  811. TokenInstruction::BurnChecked { amount, decimals } => {
  812. msg!("Instruction: BurnChecked");
  813. Self::process_burn(program_id, accounts, amount, Some(decimals))
  814. }
  815. TokenInstruction::SyncNative => {
  816. msg!("Instruction: SyncNative");
  817. Self::process_sync_native(program_id, accounts)
  818. }
  819. TokenInstruction::GetAccountDataSize => {
  820. msg!("Instruction: GetAccountDataSize");
  821. Self::process_get_account_data_size(program_id, accounts)
  822. }
  823. TokenInstruction::InitializeImmutableOwner => {
  824. msg!("Instruction: InitializeImmutableOwner");
  825. Self::process_initialize_immutable_owner(accounts)
  826. }
  827. TokenInstruction::AmountToUiAmount { amount } => {
  828. msg!("Instruction: AmountToUiAmount");
  829. Self::process_amount_to_ui_amount(program_id, accounts, amount)
  830. }
  831. TokenInstruction::UiAmountToAmount { ui_amount } => {
  832. msg!("Instruction: UiAmountToAmount");
  833. Self::process_ui_amount_to_amount(program_id, accounts, ui_amount)
  834. }
  835. }
  836. }
  837. /// Checks that the account is owned by the expected program
  838. pub fn check_account_owner(program_id: &Pubkey, account_info: &AccountInfo) -> ProgramResult {
  839. if !Self::cmp_pubkeys(program_id, account_info.owner) {
  840. Err(ProgramError::IncorrectProgramId)
  841. } else {
  842. Ok(())
  843. }
  844. }
  845. /// Checks two pubkeys for equality in a computationally cheap way using
  846. /// `sol_memcmp`
  847. pub fn cmp_pubkeys(a: &Pubkey, b: &Pubkey) -> bool {
  848. sol_memcmp(a.as_ref(), b.as_ref(), PUBKEY_BYTES) == 0
  849. }
  850. /// Validates owner(s) are present
  851. pub fn validate_owner(
  852. program_id: &Pubkey,
  853. expected_owner: &Pubkey,
  854. owner_account_info: &AccountInfo,
  855. signers: &[AccountInfo],
  856. ) -> ProgramResult {
  857. if !Self::cmp_pubkeys(expected_owner, owner_account_info.key) {
  858. return Err(TokenError::OwnerMismatch.into());
  859. }
  860. if Self::cmp_pubkeys(program_id, owner_account_info.owner)
  861. && owner_account_info.data_len() == Multisig::get_packed_len()
  862. {
  863. let multisig = Multisig::unpack(&owner_account_info.data.borrow())?;
  864. let mut num_signers = 0;
  865. let mut matched = [false; MAX_SIGNERS];
  866. for signer in signers.iter() {
  867. for (position, key) in multisig.signers[0..multisig.n as usize].iter().enumerate() {
  868. if Self::cmp_pubkeys(key, signer.key) && !matched[position] {
  869. if !signer.is_signer {
  870. return Err(ProgramError::MissingRequiredSignature);
  871. }
  872. matched[position] = true;
  873. num_signers += 1;
  874. }
  875. }
  876. }
  877. if num_signers < multisig.m {
  878. return Err(ProgramError::MissingRequiredSignature);
  879. }
  880. return Ok(());
  881. } else if !owner_account_info.is_signer {
  882. return Err(ProgramError::MissingRequiredSignature);
  883. }
  884. Ok(())
  885. }
  886. }
  887. /// Helper function to mostly delete an account in a test environment. We could
  888. /// potentially muck around the bytes assuming that a vec is passed in, but that
  889. /// would be more trouble than it's worth.
  890. #[cfg(not(target_os = "solana"))]
  891. fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
  892. account_info.assign(&system_program::id());
  893. let mut account_data = account_info.data.borrow_mut();
  894. let data_len = account_data.len();
  895. solana_program::program_memory::sol_memset(*account_data, 0, data_len);
  896. Ok(())
  897. }
  898. /// Helper function to totally delete an account on-chain
  899. #[cfg(target_os = "solana")]
  900. fn delete_account(account_info: &AccountInfo) -> Result<(), ProgramError> {
  901. account_info.assign(&system_program::id());
  902. account_info.realloc(0, false)
  903. }
  904. #[cfg(test)]
  905. mod tests {
  906. use super::*;
  907. use crate::instruction::*;
  908. use serial_test::serial;
  909. use solana_program::{
  910. account_info::IntoAccountInfo,
  911. clock::Epoch,
  912. instruction::Instruction,
  913. program_error::{self, PrintProgramError},
  914. sysvar::rent,
  915. };
  916. use solana_sdk::account::{
  917. create_account_for_test, create_is_signer_account_infos, Account as SolanaAccount,
  918. };
  919. use std::sync::{Arc, RwLock};
  920. lazy_static::lazy_static! {
  921. static ref EXPECTED_DATA: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(Vec::new()));
  922. }
  923. fn set_expected_data(expected_data: Vec<u8>) {
  924. *EXPECTED_DATA.write().unwrap() = expected_data;
  925. }
  926. struct SyscallStubs {}
  927. impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
  928. fn sol_log(&self, _message: &str) {}
  929. fn sol_invoke_signed(
  930. &self,
  931. _instruction: &Instruction,
  932. _account_infos: &[AccountInfo],
  933. _signers_seeds: &[&[&[u8]]],
  934. ) -> ProgramResult {
  935. Err(ProgramError::Custom(42)) // Not supported
  936. }
  937. fn sol_get_clock_sysvar(&self, _var_addr: *mut u8) -> u64 {
  938. program_error::UNSUPPORTED_SYSVAR
  939. }
  940. fn sol_get_epoch_schedule_sysvar(&self, _var_addr: *mut u8) -> u64 {
  941. program_error::UNSUPPORTED_SYSVAR
  942. }
  943. #[allow(deprecated)]
  944. fn sol_get_fees_sysvar(&self, _var_addr: *mut u8) -> u64 {
  945. program_error::UNSUPPORTED_SYSVAR
  946. }
  947. fn sol_get_rent_sysvar(&self, var_addr: *mut u8) -> u64 {
  948. unsafe {
  949. *(var_addr as *mut _ as *mut Rent) = Rent::default();
  950. }
  951. solana_program::entrypoint::SUCCESS
  952. }
  953. fn sol_set_return_data(&self, data: &[u8]) {
  954. assert_eq!(&*EXPECTED_DATA.write().unwrap(), data)
  955. }
  956. }
  957. fn do_process_instruction(
  958. instruction: Instruction,
  959. accounts: Vec<&mut SolanaAccount>,
  960. ) -> ProgramResult {
  961. {
  962. use std::sync::Once;
  963. static ONCE: Once = Once::new();
  964. ONCE.call_once(|| {
  965. solana_sdk::program_stubs::set_syscall_stubs(Box::new(SyscallStubs {}));
  966. });
  967. }
  968. let mut meta = instruction
  969. .accounts
  970. .iter()
  971. .zip(accounts)
  972. .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
  973. .collect::<Vec<_>>();
  974. let account_infos = create_is_signer_account_infos(&mut meta);
  975. Processor::process(&instruction.program_id, &account_infos, &instruction.data)
  976. }
  977. fn do_process_instruction_dups(
  978. instruction: Instruction,
  979. account_infos: Vec<AccountInfo>,
  980. ) -> ProgramResult {
  981. Processor::process(&instruction.program_id, &account_infos, &instruction.data)
  982. }
  983. fn return_token_error_as_program_error() -> ProgramError {
  984. TokenError::MintMismatch.into()
  985. }
  986. fn rent_sysvar() -> SolanaAccount {
  987. create_account_for_test(&Rent::default())
  988. }
  989. fn mint_minimum_balance() -> u64 {
  990. Rent::default().minimum_balance(Mint::get_packed_len())
  991. }
  992. fn account_minimum_balance() -> u64 {
  993. Rent::default().minimum_balance(Account::get_packed_len())
  994. }
  995. fn multisig_minimum_balance() -> u64 {
  996. Rent::default().minimum_balance(Multisig::get_packed_len())
  997. }
  998. #[test]
  999. fn test_print_error() {
  1000. let error = return_token_error_as_program_error();
  1001. error.print::<TokenError>();
  1002. }
  1003. #[test]
  1004. fn test_error_as_custom() {
  1005. assert_eq!(
  1006. return_token_error_as_program_error(),
  1007. ProgramError::Custom(3)
  1008. );
  1009. }
  1010. #[test]
  1011. fn test_unique_account_sizes() {
  1012. assert_ne!(Mint::get_packed_len(), 0);
  1013. assert_ne!(Mint::get_packed_len(), Account::get_packed_len());
  1014. assert_ne!(Mint::get_packed_len(), Multisig::get_packed_len());
  1015. assert_ne!(Account::get_packed_len(), 0);
  1016. assert_ne!(Account::get_packed_len(), Multisig::get_packed_len());
  1017. assert_ne!(Multisig::get_packed_len(), 0);
  1018. }
  1019. #[test]
  1020. fn test_pack_unpack() {
  1021. // Mint
  1022. let check = Mint {
  1023. mint_authority: COption::Some(Pubkey::new_from_array([1; 32])),
  1024. supply: 42,
  1025. decimals: 7,
  1026. is_initialized: true,
  1027. freeze_authority: COption::Some(Pubkey::new_from_array([2; 32])),
  1028. };
  1029. let mut packed = vec![0; Mint::get_packed_len() + 1];
  1030. assert_eq!(
  1031. Err(ProgramError::InvalidAccountData),
  1032. Mint::pack(check, &mut packed)
  1033. );
  1034. let mut packed = vec![0; Mint::get_packed_len() - 1];
  1035. assert_eq!(
  1036. Err(ProgramError::InvalidAccountData),
  1037. Mint::pack(check, &mut packed)
  1038. );
  1039. let mut packed = vec![0; Mint::get_packed_len()];
  1040. Mint::pack(check, &mut packed).unwrap();
  1041. let expect = vec![
  1042. 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1043. 1, 1, 1, 1, 1, 1, 1, 42, 0, 0, 0, 0, 0, 0, 0, 7, 1, 1, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
  1044. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1045. ];
  1046. assert_eq!(packed, expect);
  1047. let unpacked = Mint::unpack(&packed).unwrap();
  1048. assert_eq!(unpacked, check);
  1049. // Account
  1050. let check = Account {
  1051. mint: Pubkey::new_from_array([1; 32]),
  1052. owner: Pubkey::new_from_array([2; 32]),
  1053. amount: 3,
  1054. delegate: COption::Some(Pubkey::new_from_array([4; 32])),
  1055. state: AccountState::Frozen,
  1056. is_native: COption::Some(5),
  1057. delegated_amount: 6,
  1058. close_authority: COption::Some(Pubkey::new_from_array([7; 32])),
  1059. };
  1060. let mut packed = vec![0; Account::get_packed_len() + 1];
  1061. assert_eq!(
  1062. Err(ProgramError::InvalidAccountData),
  1063. Account::pack(check, &mut packed)
  1064. );
  1065. let mut packed = vec![0; Account::get_packed_len() - 1];
  1066. assert_eq!(
  1067. Err(ProgramError::InvalidAccountData),
  1068. Account::pack(check, &mut packed)
  1069. );
  1070. let mut packed = vec![0; Account::get_packed_len()];
  1071. Account::pack(check, &mut packed).unwrap();
  1072. let expect = vec![
  1073. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1074. 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  1075. 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  1076. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 0, 0, 5, 0, 0,
  1077. 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1078. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1079. ];
  1080. assert_eq!(packed, expect);
  1081. let unpacked = Account::unpack(&packed).unwrap();
  1082. assert_eq!(unpacked, check);
  1083. // Multisig
  1084. let check = Multisig {
  1085. m: 1,
  1086. n: 2,
  1087. is_initialized: true,
  1088. signers: [Pubkey::new_from_array([3; 32]); MAX_SIGNERS],
  1089. };
  1090. let mut packed = vec![0; Multisig::get_packed_len() + 1];
  1091. assert_eq!(
  1092. Err(ProgramError::InvalidAccountData),
  1093. Multisig::pack(check, &mut packed)
  1094. );
  1095. let mut packed = vec![0; Multisig::get_packed_len() - 1];
  1096. assert_eq!(
  1097. Err(ProgramError::InvalidAccountData),
  1098. Multisig::pack(check, &mut packed)
  1099. );
  1100. let mut packed = vec![0; Multisig::get_packed_len()];
  1101. Multisig::pack(check, &mut packed).unwrap();
  1102. let expect = vec![
  1103. 1, 2, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1104. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1105. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1106. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1107. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1108. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1109. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1110. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1111. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1112. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1113. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1114. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1115. 3, 3, 3, 3, 3, 3, 3,
  1116. ];
  1117. assert_eq!(packed, expect);
  1118. let unpacked = Multisig::unpack(&packed).unwrap();
  1119. assert_eq!(unpacked, check);
  1120. }
  1121. #[test]
  1122. fn test_initialize_mint() {
  1123. let program_id = crate::id();
  1124. let owner_key = Pubkey::new_unique();
  1125. let mint_key = Pubkey::new_unique();
  1126. let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
  1127. let mint2_key = Pubkey::new_unique();
  1128. let mut mint2_account =
  1129. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  1130. let mut rent_sysvar = rent_sysvar();
  1131. // mint is not rent exempt
  1132. assert_eq!(
  1133. Err(TokenError::NotRentExempt.into()),
  1134. do_process_instruction(
  1135. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1136. vec![&mut mint_account, &mut rent_sysvar]
  1137. )
  1138. );
  1139. mint_account.lamports = mint_minimum_balance();
  1140. // create new mint
  1141. do_process_instruction(
  1142. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1143. vec![&mut mint_account, &mut rent_sysvar],
  1144. )
  1145. .unwrap();
  1146. // create twice
  1147. assert_eq!(
  1148. Err(TokenError::AlreadyInUse.into()),
  1149. do_process_instruction(
  1150. initialize_mint(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
  1151. vec![&mut mint_account, &mut rent_sysvar]
  1152. )
  1153. );
  1154. // create another mint that can freeze
  1155. do_process_instruction(
  1156. initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
  1157. vec![&mut mint2_account, &mut rent_sysvar],
  1158. )
  1159. .unwrap();
  1160. let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
  1161. assert_eq!(mint.freeze_authority, COption::Some(owner_key));
  1162. }
  1163. #[test]
  1164. fn test_initialize_mint2() {
  1165. let program_id = crate::id();
  1166. let owner_key = Pubkey::new_unique();
  1167. let mint_key = Pubkey::new_unique();
  1168. let mut mint_account = SolanaAccount::new(42, Mint::get_packed_len(), &program_id);
  1169. let mint2_key = Pubkey::new_unique();
  1170. let mut mint2_account =
  1171. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  1172. // mint is not rent exempt
  1173. assert_eq!(
  1174. Err(TokenError::NotRentExempt.into()),
  1175. do_process_instruction(
  1176. initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1177. vec![&mut mint_account]
  1178. )
  1179. );
  1180. mint_account.lamports = mint_minimum_balance();
  1181. // create new mint
  1182. do_process_instruction(
  1183. initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1184. vec![&mut mint_account],
  1185. )
  1186. .unwrap();
  1187. // create twice
  1188. assert_eq!(
  1189. Err(TokenError::AlreadyInUse.into()),
  1190. do_process_instruction(
  1191. initialize_mint2(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
  1192. vec![&mut mint_account]
  1193. )
  1194. );
  1195. // create another mint that can freeze
  1196. do_process_instruction(
  1197. initialize_mint2(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
  1198. vec![&mut mint2_account],
  1199. )
  1200. .unwrap();
  1201. let mint = Mint::unpack_unchecked(&mint2_account.data).unwrap();
  1202. assert_eq!(mint.freeze_authority, COption::Some(owner_key));
  1203. }
  1204. #[test]
  1205. fn test_initialize_mint_account() {
  1206. let program_id = crate::id();
  1207. let account_key = Pubkey::new_unique();
  1208. let mut account_account = SolanaAccount::new(42, Account::get_packed_len(), &program_id);
  1209. let owner_key = Pubkey::new_unique();
  1210. let mut owner_account = SolanaAccount::default();
  1211. let mint_key = Pubkey::new_unique();
  1212. let mut mint_account =
  1213. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  1214. let mut rent_sysvar = rent_sysvar();
  1215. // account is not rent exempt
  1216. assert_eq!(
  1217. Err(TokenError::NotRentExempt.into()),
  1218. do_process_instruction(
  1219. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1220. vec![
  1221. &mut account_account,
  1222. &mut mint_account,
  1223. &mut owner_account,
  1224. &mut rent_sysvar
  1225. ],
  1226. )
  1227. );
  1228. account_account.lamports = account_minimum_balance();
  1229. // mint is not valid (not initialized)
  1230. assert_eq!(
  1231. Err(TokenError::InvalidMint.into()),
  1232. do_process_instruction(
  1233. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1234. vec![
  1235. &mut account_account,
  1236. &mut mint_account,
  1237. &mut owner_account,
  1238. &mut rent_sysvar
  1239. ],
  1240. )
  1241. );
  1242. // create mint
  1243. do_process_instruction(
  1244. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1245. vec![&mut mint_account, &mut rent_sysvar],
  1246. )
  1247. .unwrap();
  1248. // mint not owned by program
  1249. let not_program_id = Pubkey::new_unique();
  1250. mint_account.owner = not_program_id;
  1251. assert_eq!(
  1252. Err(ProgramError::IncorrectProgramId),
  1253. do_process_instruction(
  1254. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1255. vec![
  1256. &mut account_account,
  1257. &mut mint_account,
  1258. &mut owner_account,
  1259. &mut rent_sysvar
  1260. ],
  1261. )
  1262. );
  1263. mint_account.owner = program_id;
  1264. // create account
  1265. do_process_instruction(
  1266. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1267. vec![
  1268. &mut account_account,
  1269. &mut mint_account,
  1270. &mut owner_account,
  1271. &mut rent_sysvar,
  1272. ],
  1273. )
  1274. .unwrap();
  1275. // create twice
  1276. assert_eq!(
  1277. Err(TokenError::AlreadyInUse.into()),
  1278. do_process_instruction(
  1279. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1280. vec![
  1281. &mut account_account,
  1282. &mut mint_account,
  1283. &mut owner_account,
  1284. &mut rent_sysvar
  1285. ],
  1286. )
  1287. );
  1288. }
  1289. #[test]
  1290. fn test_transfer_dups() {
  1291. let program_id = crate::id();
  1292. let account1_key = Pubkey::new_unique();
  1293. let mut account1_account = SolanaAccount::new(
  1294. account_minimum_balance(),
  1295. Account::get_packed_len(),
  1296. &program_id,
  1297. );
  1298. let mut account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
  1299. let account2_key = Pubkey::new_unique();
  1300. let mut account2_account = SolanaAccount::new(
  1301. account_minimum_balance(),
  1302. Account::get_packed_len(),
  1303. &program_id,
  1304. );
  1305. let mut account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
  1306. let account3_key = Pubkey::new_unique();
  1307. let mut account3_account = SolanaAccount::new(
  1308. account_minimum_balance(),
  1309. Account::get_packed_len(),
  1310. &program_id,
  1311. );
  1312. let account3_info: AccountInfo = (&account3_key, false, &mut account3_account).into();
  1313. let account4_key = Pubkey::new_unique();
  1314. let mut account4_account = SolanaAccount::new(
  1315. account_minimum_balance(),
  1316. Account::get_packed_len(),
  1317. &program_id,
  1318. );
  1319. let account4_info: AccountInfo = (&account4_key, true, &mut account4_account).into();
  1320. let multisig_key = Pubkey::new_unique();
  1321. let mut multisig_account = SolanaAccount::new(
  1322. multisig_minimum_balance(),
  1323. Multisig::get_packed_len(),
  1324. &program_id,
  1325. );
  1326. let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
  1327. let owner_key = Pubkey::new_unique();
  1328. let mut owner_account = SolanaAccount::default();
  1329. let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
  1330. let mint_key = Pubkey::new_unique();
  1331. let mut mint_account =
  1332. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  1333. let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
  1334. let rent_key = rent::id();
  1335. let mut rent_sysvar = rent_sysvar();
  1336. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  1337. // create mint
  1338. do_process_instruction_dups(
  1339. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1340. vec![mint_info.clone(), rent_info.clone()],
  1341. )
  1342. .unwrap();
  1343. // create account
  1344. do_process_instruction_dups(
  1345. initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
  1346. vec![
  1347. account1_info.clone(),
  1348. mint_info.clone(),
  1349. account1_info.clone(),
  1350. rent_info.clone(),
  1351. ],
  1352. )
  1353. .unwrap();
  1354. // create another account
  1355. do_process_instruction_dups(
  1356. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  1357. vec![
  1358. account2_info.clone(),
  1359. mint_info.clone(),
  1360. owner_info.clone(),
  1361. rent_info.clone(),
  1362. ],
  1363. )
  1364. .unwrap();
  1365. // mint to account
  1366. do_process_instruction_dups(
  1367. mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
  1368. vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
  1369. )
  1370. .unwrap();
  1371. // source-owner transfer
  1372. do_process_instruction_dups(
  1373. transfer(
  1374. &program_id,
  1375. &account1_key,
  1376. &account2_key,
  1377. &account1_key,
  1378. &[],
  1379. 500,
  1380. )
  1381. .unwrap(),
  1382. vec![
  1383. account1_info.clone(),
  1384. account2_info.clone(),
  1385. account1_info.clone(),
  1386. ],
  1387. )
  1388. .unwrap();
  1389. // source-owner TransferChecked
  1390. do_process_instruction_dups(
  1391. transfer_checked(
  1392. &program_id,
  1393. &account1_key,
  1394. &mint_key,
  1395. &account2_key,
  1396. &account1_key,
  1397. &[],
  1398. 500,
  1399. 2,
  1400. )
  1401. .unwrap(),
  1402. vec![
  1403. account1_info.clone(),
  1404. mint_info.clone(),
  1405. account2_info.clone(),
  1406. account1_info.clone(),
  1407. ],
  1408. )
  1409. .unwrap();
  1410. // source-delegate transfer
  1411. let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
  1412. account.amount = 1000;
  1413. account.delegated_amount = 1000;
  1414. account.delegate = COption::Some(account1_key);
  1415. account.owner = owner_key;
  1416. Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
  1417. do_process_instruction_dups(
  1418. transfer(
  1419. &program_id,
  1420. &account1_key,
  1421. &account2_key,
  1422. &account1_key,
  1423. &[],
  1424. 500,
  1425. )
  1426. .unwrap(),
  1427. vec![
  1428. account1_info.clone(),
  1429. account2_info.clone(),
  1430. account1_info.clone(),
  1431. ],
  1432. )
  1433. .unwrap();
  1434. // source-delegate TransferChecked
  1435. do_process_instruction_dups(
  1436. transfer_checked(
  1437. &program_id,
  1438. &account1_key,
  1439. &mint_key,
  1440. &account2_key,
  1441. &account1_key,
  1442. &[],
  1443. 500,
  1444. 2,
  1445. )
  1446. .unwrap(),
  1447. vec![
  1448. account1_info.clone(),
  1449. mint_info.clone(),
  1450. account2_info.clone(),
  1451. account1_info.clone(),
  1452. ],
  1453. )
  1454. .unwrap();
  1455. // test destination-owner transfer
  1456. do_process_instruction_dups(
  1457. initialize_account(&program_id, &account3_key, &mint_key, &account2_key).unwrap(),
  1458. vec![
  1459. account3_info.clone(),
  1460. mint_info.clone(),
  1461. account2_info.clone(),
  1462. rent_info.clone(),
  1463. ],
  1464. )
  1465. .unwrap();
  1466. do_process_instruction_dups(
  1467. mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
  1468. vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
  1469. )
  1470. .unwrap();
  1471. account1_info.is_signer = false;
  1472. account2_info.is_signer = true;
  1473. do_process_instruction_dups(
  1474. transfer(
  1475. &program_id,
  1476. &account3_key,
  1477. &account2_key,
  1478. &account2_key,
  1479. &[],
  1480. 500,
  1481. )
  1482. .unwrap(),
  1483. vec![
  1484. account3_info.clone(),
  1485. account2_info.clone(),
  1486. account2_info.clone(),
  1487. ],
  1488. )
  1489. .unwrap();
  1490. // destination-owner TransferChecked
  1491. do_process_instruction_dups(
  1492. transfer_checked(
  1493. &program_id,
  1494. &account3_key,
  1495. &mint_key,
  1496. &account2_key,
  1497. &account2_key,
  1498. &[],
  1499. 500,
  1500. 2,
  1501. )
  1502. .unwrap(),
  1503. vec![
  1504. account3_info.clone(),
  1505. mint_info.clone(),
  1506. account2_info.clone(),
  1507. account2_info.clone(),
  1508. ],
  1509. )
  1510. .unwrap();
  1511. // test source-multisig signer
  1512. do_process_instruction_dups(
  1513. initialize_multisig(&program_id, &multisig_key, &[&account4_key], 1).unwrap(),
  1514. vec![
  1515. multisig_info.clone(),
  1516. rent_info.clone(),
  1517. account4_info.clone(),
  1518. ],
  1519. )
  1520. .unwrap();
  1521. do_process_instruction_dups(
  1522. initialize_account(&program_id, &account4_key, &mint_key, &multisig_key).unwrap(),
  1523. vec![
  1524. account4_info.clone(),
  1525. mint_info.clone(),
  1526. multisig_info.clone(),
  1527. rent_info.clone(),
  1528. ],
  1529. )
  1530. .unwrap();
  1531. do_process_instruction_dups(
  1532. mint_to(&program_id, &mint_key, &account4_key, &owner_key, &[], 1000).unwrap(),
  1533. vec![mint_info.clone(), account4_info.clone(), owner_info.clone()],
  1534. )
  1535. .unwrap();
  1536. // source-multisig-signer transfer
  1537. do_process_instruction_dups(
  1538. transfer(
  1539. &program_id,
  1540. &account4_key,
  1541. &account2_key,
  1542. &multisig_key,
  1543. &[&account4_key],
  1544. 500,
  1545. )
  1546. .unwrap(),
  1547. vec![
  1548. account4_info.clone(),
  1549. account2_info.clone(),
  1550. multisig_info.clone(),
  1551. account4_info.clone(),
  1552. ],
  1553. )
  1554. .unwrap();
  1555. // source-multisig-signer TransferChecked
  1556. do_process_instruction_dups(
  1557. transfer_checked(
  1558. &program_id,
  1559. &account4_key,
  1560. &mint_key,
  1561. &account2_key,
  1562. &multisig_key,
  1563. &[&account4_key],
  1564. 500,
  1565. 2,
  1566. )
  1567. .unwrap(),
  1568. vec![
  1569. account4_info.clone(),
  1570. mint_info.clone(),
  1571. account2_info.clone(),
  1572. multisig_info.clone(),
  1573. account4_info.clone(),
  1574. ],
  1575. )
  1576. .unwrap();
  1577. }
  1578. #[test]
  1579. fn test_transfer() {
  1580. let program_id = crate::id();
  1581. let account_key = Pubkey::new_unique();
  1582. let mut account_account = SolanaAccount::new(
  1583. account_minimum_balance(),
  1584. Account::get_packed_len(),
  1585. &program_id,
  1586. );
  1587. let account2_key = Pubkey::new_unique();
  1588. let mut account2_account = SolanaAccount::new(
  1589. account_minimum_balance(),
  1590. Account::get_packed_len(),
  1591. &program_id,
  1592. );
  1593. let account3_key = Pubkey::new_unique();
  1594. let mut account3_account = SolanaAccount::new(
  1595. account_minimum_balance(),
  1596. Account::get_packed_len(),
  1597. &program_id,
  1598. );
  1599. let delegate_key = Pubkey::new_unique();
  1600. let mut delegate_account = SolanaAccount::default();
  1601. let mismatch_key = Pubkey::new_unique();
  1602. let mut mismatch_account = SolanaAccount::new(
  1603. account_minimum_balance(),
  1604. Account::get_packed_len(),
  1605. &program_id,
  1606. );
  1607. let owner_key = Pubkey::new_unique();
  1608. let mut owner_account = SolanaAccount::default();
  1609. let owner2_key = Pubkey::new_unique();
  1610. let mut owner2_account = SolanaAccount::default();
  1611. let mint_key = Pubkey::new_unique();
  1612. let mut mint_account =
  1613. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  1614. let mint2_key = Pubkey::new_unique();
  1615. let mut rent_sysvar = rent_sysvar();
  1616. // create mint
  1617. do_process_instruction(
  1618. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1619. vec![&mut mint_account, &mut rent_sysvar],
  1620. )
  1621. .unwrap();
  1622. // create account
  1623. do_process_instruction(
  1624. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1625. vec![
  1626. &mut account_account,
  1627. &mut mint_account,
  1628. &mut owner_account,
  1629. &mut rent_sysvar,
  1630. ],
  1631. )
  1632. .unwrap();
  1633. // create another account
  1634. do_process_instruction(
  1635. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  1636. vec![
  1637. &mut account2_account,
  1638. &mut mint_account,
  1639. &mut owner_account,
  1640. &mut rent_sysvar,
  1641. ],
  1642. )
  1643. .unwrap();
  1644. // create another account
  1645. do_process_instruction(
  1646. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  1647. vec![
  1648. &mut account3_account,
  1649. &mut mint_account,
  1650. &mut owner_account,
  1651. &mut rent_sysvar,
  1652. ],
  1653. )
  1654. .unwrap();
  1655. // create mismatch account
  1656. do_process_instruction(
  1657. initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
  1658. vec![
  1659. &mut mismatch_account,
  1660. &mut mint_account,
  1661. &mut owner_account,
  1662. &mut rent_sysvar,
  1663. ],
  1664. )
  1665. .unwrap();
  1666. let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
  1667. account.mint = mint2_key;
  1668. Account::pack(account, &mut mismatch_account.data).unwrap();
  1669. // mint to account
  1670. do_process_instruction(
  1671. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  1672. vec![&mut mint_account, &mut account_account, &mut owner_account],
  1673. )
  1674. .unwrap();
  1675. // missing signer
  1676. let mut instruction = transfer(
  1677. &program_id,
  1678. &account_key,
  1679. &account2_key,
  1680. &owner_key,
  1681. &[],
  1682. 1000,
  1683. )
  1684. .unwrap();
  1685. instruction.accounts[2].is_signer = false;
  1686. assert_eq!(
  1687. Err(ProgramError::MissingRequiredSignature),
  1688. do_process_instruction(
  1689. instruction,
  1690. vec![
  1691. &mut account_account,
  1692. &mut account2_account,
  1693. &mut owner_account,
  1694. ],
  1695. )
  1696. );
  1697. // mismatch mint
  1698. assert_eq!(
  1699. Err(TokenError::MintMismatch.into()),
  1700. do_process_instruction(
  1701. transfer(
  1702. &program_id,
  1703. &account_key,
  1704. &mismatch_key,
  1705. &owner_key,
  1706. &[],
  1707. 1000
  1708. )
  1709. .unwrap(),
  1710. vec![
  1711. &mut account_account,
  1712. &mut mismatch_account,
  1713. &mut owner_account,
  1714. ],
  1715. )
  1716. );
  1717. // missing owner
  1718. assert_eq!(
  1719. Err(TokenError::OwnerMismatch.into()),
  1720. do_process_instruction(
  1721. transfer(
  1722. &program_id,
  1723. &account_key,
  1724. &account2_key,
  1725. &owner2_key,
  1726. &[],
  1727. 1000
  1728. )
  1729. .unwrap(),
  1730. vec![
  1731. &mut account_account,
  1732. &mut account2_account,
  1733. &mut owner2_account,
  1734. ],
  1735. )
  1736. );
  1737. // account not owned by program
  1738. let not_program_id = Pubkey::new_unique();
  1739. account_account.owner = not_program_id;
  1740. assert_eq!(
  1741. Err(ProgramError::IncorrectProgramId),
  1742. do_process_instruction(
  1743. transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
  1744. vec![
  1745. &mut account_account,
  1746. &mut account2_account,
  1747. &mut owner2_account,
  1748. ],
  1749. )
  1750. );
  1751. account_account.owner = program_id;
  1752. // account 2 not owned by program
  1753. let not_program_id = Pubkey::new_unique();
  1754. account2_account.owner = not_program_id;
  1755. assert_eq!(
  1756. Err(ProgramError::IncorrectProgramId),
  1757. do_process_instruction(
  1758. transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 0,).unwrap(),
  1759. vec![
  1760. &mut account_account,
  1761. &mut account2_account,
  1762. &mut owner2_account,
  1763. ],
  1764. )
  1765. );
  1766. account2_account.owner = program_id;
  1767. // transfer
  1768. do_process_instruction(
  1769. transfer(
  1770. &program_id,
  1771. &account_key,
  1772. &account2_key,
  1773. &owner_key,
  1774. &[],
  1775. 1000,
  1776. )
  1777. .unwrap(),
  1778. vec![
  1779. &mut account_account,
  1780. &mut account2_account,
  1781. &mut owner_account,
  1782. ],
  1783. )
  1784. .unwrap();
  1785. // insufficient funds
  1786. assert_eq!(
  1787. Err(TokenError::InsufficientFunds.into()),
  1788. do_process_instruction(
  1789. transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
  1790. vec![
  1791. &mut account_account,
  1792. &mut account2_account,
  1793. &mut owner_account,
  1794. ],
  1795. )
  1796. );
  1797. // transfer half back
  1798. do_process_instruction(
  1799. transfer(
  1800. &program_id,
  1801. &account2_key,
  1802. &account_key,
  1803. &owner_key,
  1804. &[],
  1805. 500,
  1806. )
  1807. .unwrap(),
  1808. vec![
  1809. &mut account2_account,
  1810. &mut account_account,
  1811. &mut owner_account,
  1812. ],
  1813. )
  1814. .unwrap();
  1815. // incorrect decimals
  1816. assert_eq!(
  1817. Err(TokenError::MintDecimalsMismatch.into()),
  1818. do_process_instruction(
  1819. transfer_checked(
  1820. &program_id,
  1821. &account2_key,
  1822. &mint_key,
  1823. &account_key,
  1824. &owner_key,
  1825. &[],
  1826. 1,
  1827. 10 // <-- incorrect decimals
  1828. )
  1829. .unwrap(),
  1830. vec![
  1831. &mut account2_account,
  1832. &mut mint_account,
  1833. &mut account_account,
  1834. &mut owner_account,
  1835. ],
  1836. )
  1837. );
  1838. // incorrect mint
  1839. assert_eq!(
  1840. Err(TokenError::MintMismatch.into()),
  1841. do_process_instruction(
  1842. transfer_checked(
  1843. &program_id,
  1844. &account2_key,
  1845. &account3_key, // <-- incorrect mint
  1846. &account_key,
  1847. &owner_key,
  1848. &[],
  1849. 1,
  1850. 2
  1851. )
  1852. .unwrap(),
  1853. vec![
  1854. &mut account2_account,
  1855. &mut account3_account, // <-- incorrect mint
  1856. &mut account_account,
  1857. &mut owner_account,
  1858. ],
  1859. )
  1860. );
  1861. // transfer rest with explicit decimals
  1862. do_process_instruction(
  1863. transfer_checked(
  1864. &program_id,
  1865. &account2_key,
  1866. &mint_key,
  1867. &account_key,
  1868. &owner_key,
  1869. &[],
  1870. 500,
  1871. 2,
  1872. )
  1873. .unwrap(),
  1874. vec![
  1875. &mut account2_account,
  1876. &mut mint_account,
  1877. &mut account_account,
  1878. &mut owner_account,
  1879. ],
  1880. )
  1881. .unwrap();
  1882. // insufficient funds
  1883. assert_eq!(
  1884. Err(TokenError::InsufficientFunds.into()),
  1885. do_process_instruction(
  1886. transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
  1887. vec![
  1888. &mut account2_account,
  1889. &mut account_account,
  1890. &mut owner_account,
  1891. ],
  1892. )
  1893. );
  1894. // approve delegate
  1895. do_process_instruction(
  1896. approve(
  1897. &program_id,
  1898. &account_key,
  1899. &delegate_key,
  1900. &owner_key,
  1901. &[],
  1902. 100,
  1903. )
  1904. .unwrap(),
  1905. vec![
  1906. &mut account_account,
  1907. &mut delegate_account,
  1908. &mut owner_account,
  1909. ],
  1910. )
  1911. .unwrap();
  1912. // not a delegate of source account
  1913. assert_eq!(
  1914. Err(TokenError::OwnerMismatch.into()),
  1915. do_process_instruction(
  1916. transfer(
  1917. &program_id,
  1918. &account_key,
  1919. &account2_key,
  1920. &owner2_key, // <-- incorrect owner or delegate
  1921. &[],
  1922. 1,
  1923. )
  1924. .unwrap(),
  1925. vec![
  1926. &mut account_account,
  1927. &mut account2_account,
  1928. &mut owner2_account,
  1929. ],
  1930. )
  1931. );
  1932. // insufficient funds approved via delegate
  1933. assert_eq!(
  1934. Err(TokenError::InsufficientFunds.into()),
  1935. do_process_instruction(
  1936. transfer(
  1937. &program_id,
  1938. &account_key,
  1939. &account2_key,
  1940. &delegate_key,
  1941. &[],
  1942. 101
  1943. )
  1944. .unwrap(),
  1945. vec![
  1946. &mut account_account,
  1947. &mut account2_account,
  1948. &mut delegate_account,
  1949. ],
  1950. )
  1951. );
  1952. // transfer via delegate
  1953. do_process_instruction(
  1954. transfer(
  1955. &program_id,
  1956. &account_key,
  1957. &account2_key,
  1958. &delegate_key,
  1959. &[],
  1960. 100,
  1961. )
  1962. .unwrap(),
  1963. vec![
  1964. &mut account_account,
  1965. &mut account2_account,
  1966. &mut delegate_account,
  1967. ],
  1968. )
  1969. .unwrap();
  1970. // insufficient funds approved via delegate
  1971. assert_eq!(
  1972. Err(TokenError::OwnerMismatch.into()),
  1973. do_process_instruction(
  1974. transfer(
  1975. &program_id,
  1976. &account_key,
  1977. &account2_key,
  1978. &delegate_key,
  1979. &[],
  1980. 1
  1981. )
  1982. .unwrap(),
  1983. vec![
  1984. &mut account_account,
  1985. &mut account2_account,
  1986. &mut delegate_account,
  1987. ],
  1988. )
  1989. );
  1990. // transfer rest
  1991. do_process_instruction(
  1992. transfer(
  1993. &program_id,
  1994. &account_key,
  1995. &account2_key,
  1996. &owner_key,
  1997. &[],
  1998. 900,
  1999. )
  2000. .unwrap(),
  2001. vec![
  2002. &mut account_account,
  2003. &mut account2_account,
  2004. &mut owner_account,
  2005. ],
  2006. )
  2007. .unwrap();
  2008. // approve delegate
  2009. do_process_instruction(
  2010. approve(
  2011. &program_id,
  2012. &account_key,
  2013. &delegate_key,
  2014. &owner_key,
  2015. &[],
  2016. 100,
  2017. )
  2018. .unwrap(),
  2019. vec![
  2020. &mut account_account,
  2021. &mut delegate_account,
  2022. &mut owner_account,
  2023. ],
  2024. )
  2025. .unwrap();
  2026. // insufficient funds in source account via delegate
  2027. assert_eq!(
  2028. Err(TokenError::InsufficientFunds.into()),
  2029. do_process_instruction(
  2030. transfer(
  2031. &program_id,
  2032. &account_key,
  2033. &account2_key,
  2034. &delegate_key,
  2035. &[],
  2036. 100
  2037. )
  2038. .unwrap(),
  2039. vec![
  2040. &mut account_account,
  2041. &mut account2_account,
  2042. &mut delegate_account,
  2043. ],
  2044. )
  2045. );
  2046. }
  2047. #[test]
  2048. fn test_self_transfer() {
  2049. let program_id = crate::id();
  2050. let account_key = Pubkey::new_unique();
  2051. let mut account_account = SolanaAccount::new(
  2052. account_minimum_balance(),
  2053. Account::get_packed_len(),
  2054. &program_id,
  2055. );
  2056. let account2_key = Pubkey::new_unique();
  2057. let mut account2_account = SolanaAccount::new(
  2058. account_minimum_balance(),
  2059. Account::get_packed_len(),
  2060. &program_id,
  2061. );
  2062. let account3_key = Pubkey::new_unique();
  2063. let mut account3_account = SolanaAccount::new(
  2064. account_minimum_balance(),
  2065. Account::get_packed_len(),
  2066. &program_id,
  2067. );
  2068. let delegate_key = Pubkey::new_unique();
  2069. let mut delegate_account = SolanaAccount::default();
  2070. let owner_key = Pubkey::new_unique();
  2071. let mut owner_account = SolanaAccount::default();
  2072. let owner2_key = Pubkey::new_unique();
  2073. let mut owner2_account = SolanaAccount::default();
  2074. let mint_key = Pubkey::new_unique();
  2075. let mut mint_account =
  2076. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  2077. let mut rent_sysvar = rent_sysvar();
  2078. // create mint
  2079. do_process_instruction(
  2080. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  2081. vec![&mut mint_account, &mut rent_sysvar],
  2082. )
  2083. .unwrap();
  2084. // create account
  2085. do_process_instruction(
  2086. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  2087. vec![
  2088. &mut account_account,
  2089. &mut mint_account,
  2090. &mut owner_account,
  2091. &mut rent_sysvar,
  2092. ],
  2093. )
  2094. .unwrap();
  2095. // create another account
  2096. do_process_instruction(
  2097. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  2098. vec![
  2099. &mut account2_account,
  2100. &mut mint_account,
  2101. &mut owner_account,
  2102. &mut rent_sysvar,
  2103. ],
  2104. )
  2105. .unwrap();
  2106. // create another account
  2107. do_process_instruction(
  2108. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  2109. vec![
  2110. &mut account3_account,
  2111. &mut mint_account,
  2112. &mut owner_account,
  2113. &mut rent_sysvar,
  2114. ],
  2115. )
  2116. .unwrap();
  2117. // mint to account
  2118. do_process_instruction(
  2119. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  2120. vec![&mut mint_account, &mut account_account, &mut owner_account],
  2121. )
  2122. .unwrap();
  2123. let account_info = (&account_key, false, &mut account_account).into_account_info();
  2124. let account3_info = (&account3_key, false, &mut account3_account).into_account_info();
  2125. let delegate_info = (&delegate_key, true, &mut delegate_account).into_account_info();
  2126. let owner_info = (&owner_key, true, &mut owner_account).into_account_info();
  2127. let owner2_info = (&owner2_key, true, &mut owner2_account).into_account_info();
  2128. let mint_info = (&mint_key, false, &mut mint_account).into_account_info();
  2129. // transfer
  2130. let instruction = transfer(
  2131. &program_id,
  2132. account_info.key,
  2133. account_info.key,
  2134. owner_info.key,
  2135. &[],
  2136. 1000,
  2137. )
  2138. .unwrap();
  2139. assert_eq!(
  2140. Ok(()),
  2141. Processor::process(
  2142. &instruction.program_id,
  2143. &[
  2144. account_info.clone(),
  2145. account_info.clone(),
  2146. owner_info.clone(),
  2147. ],
  2148. &instruction.data,
  2149. )
  2150. );
  2151. // no balance change...
  2152. let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
  2153. assert_eq!(account.amount, 1000);
  2154. // transfer checked
  2155. let instruction = transfer_checked(
  2156. &program_id,
  2157. account_info.key,
  2158. mint_info.key,
  2159. account_info.key,
  2160. owner_info.key,
  2161. &[],
  2162. 1000,
  2163. 2,
  2164. )
  2165. .unwrap();
  2166. assert_eq!(
  2167. Ok(()),
  2168. Processor::process(
  2169. &instruction.program_id,
  2170. &[
  2171. account_info.clone(),
  2172. mint_info.clone(),
  2173. account_info.clone(),
  2174. owner_info.clone(),
  2175. ],
  2176. &instruction.data,
  2177. )
  2178. );
  2179. // no balance change...
  2180. let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
  2181. assert_eq!(account.amount, 1000);
  2182. // missing signer
  2183. let mut owner_no_sign_info = owner_info.clone();
  2184. let mut instruction = transfer(
  2185. &program_id,
  2186. account_info.key,
  2187. account_info.key,
  2188. owner_no_sign_info.key,
  2189. &[],
  2190. 1000,
  2191. )
  2192. .unwrap();
  2193. instruction.accounts[2].is_signer = false;
  2194. owner_no_sign_info.is_signer = false;
  2195. assert_eq!(
  2196. Err(ProgramError::MissingRequiredSignature),
  2197. Processor::process(
  2198. &instruction.program_id,
  2199. &[
  2200. account_info.clone(),
  2201. account_info.clone(),
  2202. owner_no_sign_info.clone(),
  2203. ],
  2204. &instruction.data,
  2205. )
  2206. );
  2207. // missing signer checked
  2208. let mut instruction = transfer_checked(
  2209. &program_id,
  2210. account_info.key,
  2211. mint_info.key,
  2212. account_info.key,
  2213. owner_no_sign_info.key,
  2214. &[],
  2215. 1000,
  2216. 2,
  2217. )
  2218. .unwrap();
  2219. instruction.accounts[3].is_signer = false;
  2220. assert_eq!(
  2221. Err(ProgramError::MissingRequiredSignature),
  2222. Processor::process(
  2223. &instruction.program_id,
  2224. &[
  2225. account_info.clone(),
  2226. mint_info.clone(),
  2227. account_info.clone(),
  2228. owner_no_sign_info,
  2229. ],
  2230. &instruction.data,
  2231. )
  2232. );
  2233. // missing owner
  2234. let instruction = transfer(
  2235. &program_id,
  2236. account_info.key,
  2237. account_info.key,
  2238. owner2_info.key,
  2239. &[],
  2240. 1000,
  2241. )
  2242. .unwrap();
  2243. assert_eq!(
  2244. Err(TokenError::OwnerMismatch.into()),
  2245. Processor::process(
  2246. &instruction.program_id,
  2247. &[
  2248. account_info.clone(),
  2249. account_info.clone(),
  2250. owner2_info.clone(),
  2251. ],
  2252. &instruction.data,
  2253. )
  2254. );
  2255. // missing owner checked
  2256. let instruction = transfer_checked(
  2257. &program_id,
  2258. account_info.key,
  2259. mint_info.key,
  2260. account_info.key,
  2261. owner2_info.key,
  2262. &[],
  2263. 1000,
  2264. 2,
  2265. )
  2266. .unwrap();
  2267. assert_eq!(
  2268. Err(TokenError::OwnerMismatch.into()),
  2269. Processor::process(
  2270. &instruction.program_id,
  2271. &[
  2272. account_info.clone(),
  2273. mint_info.clone(),
  2274. account_info.clone(),
  2275. owner2_info.clone(),
  2276. ],
  2277. &instruction.data,
  2278. )
  2279. );
  2280. // insufficient funds
  2281. let instruction = transfer(
  2282. &program_id,
  2283. account_info.key,
  2284. account_info.key,
  2285. owner_info.key,
  2286. &[],
  2287. 1001,
  2288. )
  2289. .unwrap();
  2290. assert_eq!(
  2291. Err(TokenError::InsufficientFunds.into()),
  2292. Processor::process(
  2293. &instruction.program_id,
  2294. &[
  2295. account_info.clone(),
  2296. account_info.clone(),
  2297. owner_info.clone(),
  2298. ],
  2299. &instruction.data,
  2300. )
  2301. );
  2302. // insufficient funds checked
  2303. let instruction = transfer_checked(
  2304. &program_id,
  2305. account_info.key,
  2306. mint_info.key,
  2307. account_info.key,
  2308. owner_info.key,
  2309. &[],
  2310. 1001,
  2311. 2,
  2312. )
  2313. .unwrap();
  2314. assert_eq!(
  2315. Err(TokenError::InsufficientFunds.into()),
  2316. Processor::process(
  2317. &instruction.program_id,
  2318. &[
  2319. account_info.clone(),
  2320. mint_info.clone(),
  2321. account_info.clone(),
  2322. owner_info.clone(),
  2323. ],
  2324. &instruction.data,
  2325. )
  2326. );
  2327. // incorrect decimals
  2328. let instruction = transfer_checked(
  2329. &program_id,
  2330. account_info.key,
  2331. mint_info.key,
  2332. account_info.key,
  2333. owner_info.key,
  2334. &[],
  2335. 1,
  2336. 10, // <-- incorrect decimals
  2337. )
  2338. .unwrap();
  2339. assert_eq!(
  2340. Err(TokenError::MintDecimalsMismatch.into()),
  2341. Processor::process(
  2342. &instruction.program_id,
  2343. &[
  2344. account_info.clone(),
  2345. mint_info.clone(),
  2346. account_info.clone(),
  2347. owner_info.clone(),
  2348. ],
  2349. &instruction.data,
  2350. )
  2351. );
  2352. // incorrect mint
  2353. let instruction = transfer_checked(
  2354. &program_id,
  2355. account_info.key,
  2356. account3_info.key, // <-- incorrect mint
  2357. account_info.key,
  2358. owner_info.key,
  2359. &[],
  2360. 1,
  2361. 2,
  2362. )
  2363. .unwrap();
  2364. assert_eq!(
  2365. Err(TokenError::MintMismatch.into()),
  2366. Processor::process(
  2367. &instruction.program_id,
  2368. &[
  2369. account_info.clone(),
  2370. account3_info.clone(), // <-- incorrect mint
  2371. account_info.clone(),
  2372. owner_info.clone(),
  2373. ],
  2374. &instruction.data,
  2375. )
  2376. );
  2377. // approve delegate
  2378. let instruction = approve(
  2379. &program_id,
  2380. account_info.key,
  2381. delegate_info.key,
  2382. owner_info.key,
  2383. &[],
  2384. 100,
  2385. )
  2386. .unwrap();
  2387. Processor::process(
  2388. &instruction.program_id,
  2389. &[
  2390. account_info.clone(),
  2391. delegate_info.clone(),
  2392. owner_info.clone(),
  2393. ],
  2394. &instruction.data,
  2395. )
  2396. .unwrap();
  2397. // delegate transfer
  2398. let instruction = transfer(
  2399. &program_id,
  2400. account_info.key,
  2401. account_info.key,
  2402. delegate_info.key,
  2403. &[],
  2404. 100,
  2405. )
  2406. .unwrap();
  2407. assert_eq!(
  2408. Ok(()),
  2409. Processor::process(
  2410. &instruction.program_id,
  2411. &[
  2412. account_info.clone(),
  2413. account_info.clone(),
  2414. delegate_info.clone(),
  2415. ],
  2416. &instruction.data,
  2417. )
  2418. );
  2419. // no balance change...
  2420. let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
  2421. assert_eq!(account.amount, 1000);
  2422. assert_eq!(account.delegated_amount, 100);
  2423. // delegate transfer checked
  2424. let instruction = transfer_checked(
  2425. &program_id,
  2426. account_info.key,
  2427. mint_info.key,
  2428. account_info.key,
  2429. delegate_info.key,
  2430. &[],
  2431. 100,
  2432. 2,
  2433. )
  2434. .unwrap();
  2435. assert_eq!(
  2436. Ok(()),
  2437. Processor::process(
  2438. &instruction.program_id,
  2439. &[
  2440. account_info.clone(),
  2441. mint_info.clone(),
  2442. account_info.clone(),
  2443. delegate_info.clone(),
  2444. ],
  2445. &instruction.data,
  2446. )
  2447. );
  2448. // no balance change...
  2449. let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
  2450. assert_eq!(account.amount, 1000);
  2451. assert_eq!(account.delegated_amount, 100);
  2452. // delegate insufficient funds
  2453. let instruction = transfer(
  2454. &program_id,
  2455. account_info.key,
  2456. account_info.key,
  2457. delegate_info.key,
  2458. &[],
  2459. 101,
  2460. )
  2461. .unwrap();
  2462. assert_eq!(
  2463. Err(TokenError::InsufficientFunds.into()),
  2464. Processor::process(
  2465. &instruction.program_id,
  2466. &[
  2467. account_info.clone(),
  2468. account_info.clone(),
  2469. delegate_info.clone(),
  2470. ],
  2471. &instruction.data,
  2472. )
  2473. );
  2474. // delegate insufficient funds checked
  2475. let instruction = transfer_checked(
  2476. &program_id,
  2477. account_info.key,
  2478. mint_info.key,
  2479. account_info.key,
  2480. delegate_info.key,
  2481. &[],
  2482. 101,
  2483. 2,
  2484. )
  2485. .unwrap();
  2486. assert_eq!(
  2487. Err(TokenError::InsufficientFunds.into()),
  2488. Processor::process(
  2489. &instruction.program_id,
  2490. &[
  2491. account_info.clone(),
  2492. mint_info.clone(),
  2493. account_info.clone(),
  2494. delegate_info.clone(),
  2495. ],
  2496. &instruction.data,
  2497. )
  2498. );
  2499. // owner transfer with delegate assigned
  2500. let instruction = transfer(
  2501. &program_id,
  2502. account_info.key,
  2503. account_info.key,
  2504. owner_info.key,
  2505. &[],
  2506. 1000,
  2507. )
  2508. .unwrap();
  2509. assert_eq!(
  2510. Ok(()),
  2511. Processor::process(
  2512. &instruction.program_id,
  2513. &[
  2514. account_info.clone(),
  2515. account_info.clone(),
  2516. owner_info.clone(),
  2517. ],
  2518. &instruction.data,
  2519. )
  2520. );
  2521. // no balance change...
  2522. let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
  2523. assert_eq!(account.amount, 1000);
  2524. // owner transfer with delegate assigned checked
  2525. let instruction = transfer_checked(
  2526. &program_id,
  2527. account_info.key,
  2528. mint_info.key,
  2529. account_info.key,
  2530. owner_info.key,
  2531. &[],
  2532. 1000,
  2533. 2,
  2534. )
  2535. .unwrap();
  2536. assert_eq!(
  2537. Ok(()),
  2538. Processor::process(
  2539. &instruction.program_id,
  2540. &[
  2541. account_info.clone(),
  2542. mint_info.clone(),
  2543. account_info.clone(),
  2544. owner_info.clone(),
  2545. ],
  2546. &instruction.data,
  2547. )
  2548. );
  2549. // no balance change...
  2550. let account = Account::unpack_unchecked(&account_info.try_borrow_data().unwrap()).unwrap();
  2551. assert_eq!(account.amount, 1000);
  2552. }
  2553. #[test]
  2554. fn test_mintable_token_with_zero_supply() {
  2555. let program_id = crate::id();
  2556. let account_key = Pubkey::new_unique();
  2557. let mut account_account = SolanaAccount::new(
  2558. account_minimum_balance(),
  2559. Account::get_packed_len(),
  2560. &program_id,
  2561. );
  2562. let owner_key = Pubkey::new_unique();
  2563. let mut owner_account = SolanaAccount::default();
  2564. let mint_key = Pubkey::new_unique();
  2565. let mut mint_account =
  2566. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  2567. let mut rent_sysvar = rent_sysvar();
  2568. // create mint-able token with zero supply
  2569. let decimals = 2;
  2570. do_process_instruction(
  2571. initialize_mint(&program_id, &mint_key, &owner_key, None, decimals).unwrap(),
  2572. vec![&mut mint_account, &mut rent_sysvar],
  2573. )
  2574. .unwrap();
  2575. let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
  2576. assert_eq!(
  2577. mint,
  2578. Mint {
  2579. mint_authority: COption::Some(owner_key),
  2580. supply: 0,
  2581. decimals,
  2582. is_initialized: true,
  2583. freeze_authority: COption::None,
  2584. }
  2585. );
  2586. // create account
  2587. do_process_instruction(
  2588. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  2589. vec![
  2590. &mut account_account,
  2591. &mut mint_account,
  2592. &mut owner_account,
  2593. &mut rent_sysvar,
  2594. ],
  2595. )
  2596. .unwrap();
  2597. // mint to
  2598. do_process_instruction(
  2599. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
  2600. vec![&mut mint_account, &mut account_account, &mut owner_account],
  2601. )
  2602. .unwrap();
  2603. let _ = Mint::unpack(&mint_account.data).unwrap();
  2604. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  2605. assert_eq!(account.amount, 42);
  2606. // mint to 2, with incorrect decimals
  2607. assert_eq!(
  2608. Err(TokenError::MintDecimalsMismatch.into()),
  2609. do_process_instruction(
  2610. mint_to_checked(
  2611. &program_id,
  2612. &mint_key,
  2613. &account_key,
  2614. &owner_key,
  2615. &[],
  2616. 42,
  2617. decimals + 1
  2618. )
  2619. .unwrap(),
  2620. vec![&mut mint_account, &mut account_account, &mut owner_account],
  2621. )
  2622. );
  2623. let _ = Mint::unpack(&mint_account.data).unwrap();
  2624. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  2625. assert_eq!(account.amount, 42);
  2626. // mint to 2
  2627. do_process_instruction(
  2628. mint_to_checked(
  2629. &program_id,
  2630. &mint_key,
  2631. &account_key,
  2632. &owner_key,
  2633. &[],
  2634. 42,
  2635. decimals,
  2636. )
  2637. .unwrap(),
  2638. vec![&mut mint_account, &mut account_account, &mut owner_account],
  2639. )
  2640. .unwrap();
  2641. let _ = Mint::unpack(&mint_account.data).unwrap();
  2642. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  2643. assert_eq!(account.amount, 84);
  2644. }
  2645. #[test]
  2646. fn test_approve_dups() {
  2647. let program_id = crate::id();
  2648. let account1_key = Pubkey::new_unique();
  2649. let mut account1_account = SolanaAccount::new(
  2650. account_minimum_balance(),
  2651. Account::get_packed_len(),
  2652. &program_id,
  2653. );
  2654. let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
  2655. let account2_key = Pubkey::new_unique();
  2656. let mut account2_account = SolanaAccount::new(
  2657. account_minimum_balance(),
  2658. Account::get_packed_len(),
  2659. &program_id,
  2660. );
  2661. let account2_info: AccountInfo = (&account2_key, false, &mut account2_account).into();
  2662. let account3_key = Pubkey::new_unique();
  2663. let mut account3_account = SolanaAccount::new(
  2664. account_minimum_balance(),
  2665. Account::get_packed_len(),
  2666. &program_id,
  2667. );
  2668. let account3_info: AccountInfo = (&account3_key, true, &mut account3_account).into();
  2669. let multisig_key = Pubkey::new_unique();
  2670. let mut multisig_account = SolanaAccount::new(
  2671. multisig_minimum_balance(),
  2672. Multisig::get_packed_len(),
  2673. &program_id,
  2674. );
  2675. let multisig_info: AccountInfo = (&multisig_key, true, &mut multisig_account).into();
  2676. let owner_key = Pubkey::new_unique();
  2677. let mut owner_account = SolanaAccount::default();
  2678. let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
  2679. let mint_key = Pubkey::new_unique();
  2680. let mut mint_account =
  2681. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  2682. let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
  2683. let rent_key = rent::id();
  2684. let mut rent_sysvar = rent_sysvar();
  2685. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  2686. // create mint
  2687. do_process_instruction_dups(
  2688. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  2689. vec![mint_info.clone(), rent_info.clone()],
  2690. )
  2691. .unwrap();
  2692. // create account
  2693. do_process_instruction_dups(
  2694. initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
  2695. vec![
  2696. account1_info.clone(),
  2697. mint_info.clone(),
  2698. account1_info.clone(),
  2699. rent_info.clone(),
  2700. ],
  2701. )
  2702. .unwrap();
  2703. // create another account
  2704. do_process_instruction_dups(
  2705. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  2706. vec![
  2707. account2_info.clone(),
  2708. mint_info.clone(),
  2709. owner_info.clone(),
  2710. rent_info.clone(),
  2711. ],
  2712. )
  2713. .unwrap();
  2714. // mint to account
  2715. do_process_instruction_dups(
  2716. mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
  2717. vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
  2718. )
  2719. .unwrap();
  2720. // source-owner approve
  2721. do_process_instruction_dups(
  2722. approve(
  2723. &program_id,
  2724. &account1_key,
  2725. &account2_key,
  2726. &account1_key,
  2727. &[],
  2728. 500,
  2729. )
  2730. .unwrap(),
  2731. vec![
  2732. account1_info.clone(),
  2733. account2_info.clone(),
  2734. account1_info.clone(),
  2735. ],
  2736. )
  2737. .unwrap();
  2738. // source-owner approve_checked
  2739. do_process_instruction_dups(
  2740. approve_checked(
  2741. &program_id,
  2742. &account1_key,
  2743. &mint_key,
  2744. &account2_key,
  2745. &account1_key,
  2746. &[],
  2747. 500,
  2748. 2,
  2749. )
  2750. .unwrap(),
  2751. vec![
  2752. account1_info.clone(),
  2753. mint_info.clone(),
  2754. account2_info.clone(),
  2755. account1_info.clone(),
  2756. ],
  2757. )
  2758. .unwrap();
  2759. // source-owner revoke
  2760. do_process_instruction_dups(
  2761. revoke(&program_id, &account1_key, &account1_key, &[]).unwrap(),
  2762. vec![account1_info.clone(), account1_info.clone()],
  2763. )
  2764. .unwrap();
  2765. // test source-multisig signer
  2766. do_process_instruction_dups(
  2767. initialize_multisig(&program_id, &multisig_key, &[&account3_key], 1).unwrap(),
  2768. vec![
  2769. multisig_info.clone(),
  2770. rent_info.clone(),
  2771. account3_info.clone(),
  2772. ],
  2773. )
  2774. .unwrap();
  2775. do_process_instruction_dups(
  2776. initialize_account(&program_id, &account3_key, &mint_key, &multisig_key).unwrap(),
  2777. vec![
  2778. account3_info.clone(),
  2779. mint_info.clone(),
  2780. multisig_info.clone(),
  2781. rent_info.clone(),
  2782. ],
  2783. )
  2784. .unwrap();
  2785. do_process_instruction_dups(
  2786. mint_to(&program_id, &mint_key, &account3_key, &owner_key, &[], 1000).unwrap(),
  2787. vec![mint_info.clone(), account3_info.clone(), owner_info.clone()],
  2788. )
  2789. .unwrap();
  2790. // source-multisig-signer approve
  2791. do_process_instruction_dups(
  2792. approve(
  2793. &program_id,
  2794. &account3_key,
  2795. &account2_key,
  2796. &multisig_key,
  2797. &[&account3_key],
  2798. 500,
  2799. )
  2800. .unwrap(),
  2801. vec![
  2802. account3_info.clone(),
  2803. account2_info.clone(),
  2804. multisig_info.clone(),
  2805. account3_info.clone(),
  2806. ],
  2807. )
  2808. .unwrap();
  2809. // source-multisig-signer approve_checked
  2810. do_process_instruction_dups(
  2811. approve_checked(
  2812. &program_id,
  2813. &account3_key,
  2814. &mint_key,
  2815. &account2_key,
  2816. &multisig_key,
  2817. &[&account3_key],
  2818. 500,
  2819. 2,
  2820. )
  2821. .unwrap(),
  2822. vec![
  2823. account3_info.clone(),
  2824. mint_info.clone(),
  2825. account2_info.clone(),
  2826. multisig_info.clone(),
  2827. account3_info.clone(),
  2828. ],
  2829. )
  2830. .unwrap();
  2831. // source-owner multisig-signer
  2832. do_process_instruction_dups(
  2833. revoke(&program_id, &account3_key, &multisig_key, &[&account3_key]).unwrap(),
  2834. vec![
  2835. account3_info.clone(),
  2836. multisig_info.clone(),
  2837. account3_info.clone(),
  2838. ],
  2839. )
  2840. .unwrap();
  2841. }
  2842. #[test]
  2843. fn test_approve() {
  2844. let program_id = crate::id();
  2845. let account_key = Pubkey::new_unique();
  2846. let mut account_account = SolanaAccount::new(
  2847. account_minimum_balance(),
  2848. Account::get_packed_len(),
  2849. &program_id,
  2850. );
  2851. let account2_key = Pubkey::new_unique();
  2852. let mut account2_account = SolanaAccount::new(
  2853. account_minimum_balance(),
  2854. Account::get_packed_len(),
  2855. &program_id,
  2856. );
  2857. let delegate_key = Pubkey::new_unique();
  2858. let mut delegate_account = SolanaAccount::default();
  2859. let owner_key = Pubkey::new_unique();
  2860. let mut owner_account = SolanaAccount::default();
  2861. let owner2_key = Pubkey::new_unique();
  2862. let mut owner2_account = SolanaAccount::default();
  2863. let mint_key = Pubkey::new_unique();
  2864. let mut mint_account =
  2865. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  2866. let mut rent_sysvar = rent_sysvar();
  2867. // create mint
  2868. do_process_instruction(
  2869. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  2870. vec![&mut mint_account, &mut rent_sysvar],
  2871. )
  2872. .unwrap();
  2873. // create account
  2874. do_process_instruction(
  2875. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  2876. vec![
  2877. &mut account_account,
  2878. &mut mint_account,
  2879. &mut owner_account,
  2880. &mut rent_sysvar,
  2881. ],
  2882. )
  2883. .unwrap();
  2884. // create another account
  2885. do_process_instruction(
  2886. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  2887. vec![
  2888. &mut account2_account,
  2889. &mut mint_account,
  2890. &mut owner_account,
  2891. &mut rent_sysvar,
  2892. ],
  2893. )
  2894. .unwrap();
  2895. // mint to account
  2896. do_process_instruction(
  2897. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  2898. vec![&mut mint_account, &mut account_account, &mut owner_account],
  2899. )
  2900. .unwrap();
  2901. // missing signer
  2902. let mut instruction = approve(
  2903. &program_id,
  2904. &account_key,
  2905. &delegate_key,
  2906. &owner_key,
  2907. &[],
  2908. 100,
  2909. )
  2910. .unwrap();
  2911. instruction.accounts[2].is_signer = false;
  2912. assert_eq!(
  2913. Err(ProgramError::MissingRequiredSignature),
  2914. do_process_instruction(
  2915. instruction,
  2916. vec![
  2917. &mut account_account,
  2918. &mut delegate_account,
  2919. &mut owner_account,
  2920. ],
  2921. )
  2922. );
  2923. // no owner
  2924. assert_eq!(
  2925. Err(TokenError::OwnerMismatch.into()),
  2926. do_process_instruction(
  2927. approve(
  2928. &program_id,
  2929. &account_key,
  2930. &delegate_key,
  2931. &owner2_key,
  2932. &[],
  2933. 100
  2934. )
  2935. .unwrap(),
  2936. vec![
  2937. &mut account_account,
  2938. &mut delegate_account,
  2939. &mut owner2_account,
  2940. ],
  2941. )
  2942. );
  2943. // approve delegate
  2944. do_process_instruction(
  2945. approve(
  2946. &program_id,
  2947. &account_key,
  2948. &delegate_key,
  2949. &owner_key,
  2950. &[],
  2951. 100,
  2952. )
  2953. .unwrap(),
  2954. vec![
  2955. &mut account_account,
  2956. &mut delegate_account,
  2957. &mut owner_account,
  2958. ],
  2959. )
  2960. .unwrap();
  2961. // approve delegate 2, with incorrect decimals
  2962. assert_eq!(
  2963. Err(TokenError::MintDecimalsMismatch.into()),
  2964. do_process_instruction(
  2965. approve_checked(
  2966. &program_id,
  2967. &account_key,
  2968. &mint_key,
  2969. &delegate_key,
  2970. &owner_key,
  2971. &[],
  2972. 100,
  2973. 0 // <-- incorrect decimals
  2974. )
  2975. .unwrap(),
  2976. vec![
  2977. &mut account_account,
  2978. &mut mint_account,
  2979. &mut delegate_account,
  2980. &mut owner_account,
  2981. ],
  2982. )
  2983. );
  2984. // approve delegate 2, with incorrect mint
  2985. assert_eq!(
  2986. Err(TokenError::MintMismatch.into()),
  2987. do_process_instruction(
  2988. approve_checked(
  2989. &program_id,
  2990. &account_key,
  2991. &account2_key, // <-- bad mint
  2992. &delegate_key,
  2993. &owner_key,
  2994. &[],
  2995. 100,
  2996. 0
  2997. )
  2998. .unwrap(),
  2999. vec![
  3000. &mut account_account,
  3001. &mut account2_account, // <-- bad mint
  3002. &mut delegate_account,
  3003. &mut owner_account,
  3004. ],
  3005. )
  3006. );
  3007. // approve delegate 2
  3008. do_process_instruction(
  3009. approve_checked(
  3010. &program_id,
  3011. &account_key,
  3012. &mint_key,
  3013. &delegate_key,
  3014. &owner_key,
  3015. &[],
  3016. 100,
  3017. 2,
  3018. )
  3019. .unwrap(),
  3020. vec![
  3021. &mut account_account,
  3022. &mut mint_account,
  3023. &mut delegate_account,
  3024. &mut owner_account,
  3025. ],
  3026. )
  3027. .unwrap();
  3028. // revoke delegate
  3029. do_process_instruction(
  3030. revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
  3031. vec![&mut account_account, &mut owner_account],
  3032. )
  3033. .unwrap();
  3034. }
  3035. #[test]
  3036. fn test_set_authority_dups() {
  3037. let program_id = crate::id();
  3038. let account1_key = Pubkey::new_unique();
  3039. let mut account1_account = SolanaAccount::new(
  3040. account_minimum_balance(),
  3041. Account::get_packed_len(),
  3042. &program_id,
  3043. );
  3044. let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
  3045. let owner_key = Pubkey::new_unique();
  3046. let mint_key = Pubkey::new_unique();
  3047. let mut mint_account =
  3048. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  3049. let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
  3050. let rent_key = rent::id();
  3051. let mut rent_sysvar = rent_sysvar();
  3052. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  3053. // create mint
  3054. do_process_instruction_dups(
  3055. initialize_mint(&program_id, &mint_key, &mint_key, Some(&mint_key), 2).unwrap(),
  3056. vec![mint_info.clone(), rent_info.clone()],
  3057. )
  3058. .unwrap();
  3059. // create account
  3060. do_process_instruction_dups(
  3061. initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
  3062. vec![
  3063. account1_info.clone(),
  3064. mint_info.clone(),
  3065. account1_info.clone(),
  3066. rent_info.clone(),
  3067. ],
  3068. )
  3069. .unwrap();
  3070. // set mint_authority when currently self
  3071. do_process_instruction_dups(
  3072. set_authority(
  3073. &program_id,
  3074. &mint_key,
  3075. Some(&owner_key),
  3076. AuthorityType::MintTokens,
  3077. &mint_key,
  3078. &[],
  3079. )
  3080. .unwrap(),
  3081. vec![mint_info.clone(), mint_info.clone()],
  3082. )
  3083. .unwrap();
  3084. // set freeze_authority when currently self
  3085. do_process_instruction_dups(
  3086. set_authority(
  3087. &program_id,
  3088. &mint_key,
  3089. Some(&owner_key),
  3090. AuthorityType::FreezeAccount,
  3091. &mint_key,
  3092. &[],
  3093. )
  3094. .unwrap(),
  3095. vec![mint_info.clone(), mint_info.clone()],
  3096. )
  3097. .unwrap();
  3098. // set account owner when currently self
  3099. do_process_instruction_dups(
  3100. set_authority(
  3101. &program_id,
  3102. &account1_key,
  3103. Some(&owner_key),
  3104. AuthorityType::AccountOwner,
  3105. &account1_key,
  3106. &[],
  3107. )
  3108. .unwrap(),
  3109. vec![account1_info.clone(), account1_info.clone()],
  3110. )
  3111. .unwrap();
  3112. // set close_authority when currently self
  3113. let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
  3114. account.close_authority = COption::Some(account1_key);
  3115. Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
  3116. do_process_instruction_dups(
  3117. set_authority(
  3118. &program_id,
  3119. &account1_key,
  3120. Some(&owner_key),
  3121. AuthorityType::CloseAccount,
  3122. &account1_key,
  3123. &[],
  3124. )
  3125. .unwrap(),
  3126. vec![account1_info.clone(), account1_info.clone()],
  3127. )
  3128. .unwrap();
  3129. }
  3130. #[test]
  3131. fn test_set_authority() {
  3132. let program_id = crate::id();
  3133. let account_key = Pubkey::new_unique();
  3134. let mut account_account = SolanaAccount::new(
  3135. account_minimum_balance(),
  3136. Account::get_packed_len(),
  3137. &program_id,
  3138. );
  3139. let account2_key = Pubkey::new_unique();
  3140. let mut account2_account = SolanaAccount::new(
  3141. account_minimum_balance(),
  3142. Account::get_packed_len(),
  3143. &program_id,
  3144. );
  3145. let owner_key = Pubkey::new_unique();
  3146. let mut owner_account = SolanaAccount::default();
  3147. let owner2_key = Pubkey::new_unique();
  3148. let mut owner2_account = SolanaAccount::default();
  3149. let owner3_key = Pubkey::new_unique();
  3150. let mut owner3_account = SolanaAccount::default();
  3151. let mint_key = Pubkey::new_unique();
  3152. let mut mint_account =
  3153. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  3154. let mint2_key = Pubkey::new_unique();
  3155. let mut mint2_account =
  3156. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  3157. let mut rent_sysvar = rent_sysvar();
  3158. // create new mint with owner
  3159. do_process_instruction(
  3160. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  3161. vec![&mut mint_account, &mut rent_sysvar],
  3162. )
  3163. .unwrap();
  3164. // create mint with owner and freeze_authority
  3165. do_process_instruction(
  3166. initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
  3167. vec![&mut mint2_account, &mut rent_sysvar],
  3168. )
  3169. .unwrap();
  3170. // invalid account
  3171. assert_eq!(
  3172. Err(ProgramError::UninitializedAccount),
  3173. do_process_instruction(
  3174. set_authority(
  3175. &program_id,
  3176. &account_key,
  3177. Some(&owner2_key),
  3178. AuthorityType::AccountOwner,
  3179. &owner_key,
  3180. &[]
  3181. )
  3182. .unwrap(),
  3183. vec![&mut account_account, &mut owner_account],
  3184. )
  3185. );
  3186. // create account
  3187. do_process_instruction(
  3188. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  3189. vec![
  3190. &mut account_account,
  3191. &mut mint_account,
  3192. &mut owner_account,
  3193. &mut rent_sysvar,
  3194. ],
  3195. )
  3196. .unwrap();
  3197. // create another account
  3198. do_process_instruction(
  3199. initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
  3200. vec![
  3201. &mut account2_account,
  3202. &mut mint2_account,
  3203. &mut owner_account,
  3204. &mut rent_sysvar,
  3205. ],
  3206. )
  3207. .unwrap();
  3208. // missing owner
  3209. assert_eq!(
  3210. Err(TokenError::OwnerMismatch.into()),
  3211. do_process_instruction(
  3212. set_authority(
  3213. &program_id,
  3214. &account_key,
  3215. Some(&owner_key),
  3216. AuthorityType::AccountOwner,
  3217. &owner2_key,
  3218. &[]
  3219. )
  3220. .unwrap(),
  3221. vec![&mut account_account, &mut owner2_account],
  3222. )
  3223. );
  3224. // owner did not sign
  3225. let mut instruction = set_authority(
  3226. &program_id,
  3227. &account_key,
  3228. Some(&owner2_key),
  3229. AuthorityType::AccountOwner,
  3230. &owner_key,
  3231. &[],
  3232. )
  3233. .unwrap();
  3234. instruction.accounts[1].is_signer = false;
  3235. assert_eq!(
  3236. Err(ProgramError::MissingRequiredSignature),
  3237. do_process_instruction(instruction, vec![&mut account_account, &mut owner_account,],)
  3238. );
  3239. // wrong authority type
  3240. assert_eq!(
  3241. Err(TokenError::AuthorityTypeNotSupported.into()),
  3242. do_process_instruction(
  3243. set_authority(
  3244. &program_id,
  3245. &account_key,
  3246. Some(&owner2_key),
  3247. AuthorityType::FreezeAccount,
  3248. &owner_key,
  3249. &[],
  3250. )
  3251. .unwrap(),
  3252. vec![&mut account_account, &mut owner_account],
  3253. )
  3254. );
  3255. // account owner may not be set to None
  3256. assert_eq!(
  3257. Err(TokenError::InvalidInstruction.into()),
  3258. do_process_instruction(
  3259. set_authority(
  3260. &program_id,
  3261. &account_key,
  3262. None,
  3263. AuthorityType::AccountOwner,
  3264. &owner_key,
  3265. &[],
  3266. )
  3267. .unwrap(),
  3268. vec![&mut account_account, &mut owner_account],
  3269. )
  3270. );
  3271. // set delegate
  3272. do_process_instruction(
  3273. approve(
  3274. &program_id,
  3275. &account_key,
  3276. &owner2_key,
  3277. &owner_key,
  3278. &[],
  3279. u64::MAX,
  3280. )
  3281. .unwrap(),
  3282. vec![
  3283. &mut account_account,
  3284. &mut owner2_account,
  3285. &mut owner_account,
  3286. ],
  3287. )
  3288. .unwrap();
  3289. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  3290. assert_eq!(account.delegate, COption::Some(owner2_key));
  3291. assert_eq!(account.delegated_amount, u64::MAX);
  3292. // set owner
  3293. do_process_instruction(
  3294. set_authority(
  3295. &program_id,
  3296. &account_key,
  3297. Some(&owner3_key),
  3298. AuthorityType::AccountOwner,
  3299. &owner_key,
  3300. &[],
  3301. )
  3302. .unwrap(),
  3303. vec![&mut account_account, &mut owner_account],
  3304. )
  3305. .unwrap();
  3306. // check delegate cleared
  3307. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  3308. assert_eq!(account.delegate, COption::None);
  3309. assert_eq!(account.delegated_amount, 0);
  3310. // set owner without existing delegate
  3311. do_process_instruction(
  3312. set_authority(
  3313. &program_id,
  3314. &account_key,
  3315. Some(&owner2_key),
  3316. AuthorityType::AccountOwner,
  3317. &owner3_key,
  3318. &[],
  3319. )
  3320. .unwrap(),
  3321. vec![&mut account_account, &mut owner3_account],
  3322. )
  3323. .unwrap();
  3324. // set close_authority
  3325. do_process_instruction(
  3326. set_authority(
  3327. &program_id,
  3328. &account_key,
  3329. Some(&owner2_key),
  3330. AuthorityType::CloseAccount,
  3331. &owner2_key,
  3332. &[],
  3333. )
  3334. .unwrap(),
  3335. vec![&mut account_account, &mut owner2_account],
  3336. )
  3337. .unwrap();
  3338. // close_authority may be set to None
  3339. do_process_instruction(
  3340. set_authority(
  3341. &program_id,
  3342. &account_key,
  3343. None,
  3344. AuthorityType::CloseAccount,
  3345. &owner2_key,
  3346. &[],
  3347. )
  3348. .unwrap(),
  3349. vec![&mut account_account, &mut owner2_account],
  3350. )
  3351. .unwrap();
  3352. // wrong owner
  3353. assert_eq!(
  3354. Err(TokenError::OwnerMismatch.into()),
  3355. do_process_instruction(
  3356. set_authority(
  3357. &program_id,
  3358. &mint_key,
  3359. Some(&owner3_key),
  3360. AuthorityType::MintTokens,
  3361. &owner2_key,
  3362. &[]
  3363. )
  3364. .unwrap(),
  3365. vec![&mut mint_account, &mut owner2_account],
  3366. )
  3367. );
  3368. // owner did not sign
  3369. let mut instruction = set_authority(
  3370. &program_id,
  3371. &mint_key,
  3372. Some(&owner2_key),
  3373. AuthorityType::MintTokens,
  3374. &owner_key,
  3375. &[],
  3376. )
  3377. .unwrap();
  3378. instruction.accounts[1].is_signer = false;
  3379. assert_eq!(
  3380. Err(ProgramError::MissingRequiredSignature),
  3381. do_process_instruction(instruction, vec![&mut mint_account, &mut owner_account],)
  3382. );
  3383. // cannot freeze
  3384. assert_eq!(
  3385. Err(TokenError::MintCannotFreeze.into()),
  3386. do_process_instruction(
  3387. set_authority(
  3388. &program_id,
  3389. &mint_key,
  3390. Some(&owner2_key),
  3391. AuthorityType::FreezeAccount,
  3392. &owner_key,
  3393. &[],
  3394. )
  3395. .unwrap(),
  3396. vec![&mut mint_account, &mut owner_account],
  3397. )
  3398. );
  3399. // set owner
  3400. do_process_instruction(
  3401. set_authority(
  3402. &program_id,
  3403. &mint_key,
  3404. Some(&owner2_key),
  3405. AuthorityType::MintTokens,
  3406. &owner_key,
  3407. &[],
  3408. )
  3409. .unwrap(),
  3410. vec![&mut mint_account, &mut owner_account],
  3411. )
  3412. .unwrap();
  3413. // set owner to None
  3414. do_process_instruction(
  3415. set_authority(
  3416. &program_id,
  3417. &mint_key,
  3418. None,
  3419. AuthorityType::MintTokens,
  3420. &owner2_key,
  3421. &[],
  3422. )
  3423. .unwrap(),
  3424. vec![&mut mint_account, &mut owner2_account],
  3425. )
  3426. .unwrap();
  3427. // test unsetting mint_authority is one-way operation
  3428. assert_eq!(
  3429. Err(TokenError::FixedSupply.into()),
  3430. do_process_instruction(
  3431. set_authority(
  3432. &program_id,
  3433. &mint2_key,
  3434. Some(&owner2_key),
  3435. AuthorityType::MintTokens,
  3436. &owner_key,
  3437. &[]
  3438. )
  3439. .unwrap(),
  3440. vec![&mut mint_account, &mut owner_account],
  3441. )
  3442. );
  3443. // set freeze_authority
  3444. do_process_instruction(
  3445. set_authority(
  3446. &program_id,
  3447. &mint2_key,
  3448. Some(&owner2_key),
  3449. AuthorityType::FreezeAccount,
  3450. &owner_key,
  3451. &[],
  3452. )
  3453. .unwrap(),
  3454. vec![&mut mint2_account, &mut owner_account],
  3455. )
  3456. .unwrap();
  3457. // test unsetting freeze_authority is one-way operation
  3458. do_process_instruction(
  3459. set_authority(
  3460. &program_id,
  3461. &mint2_key,
  3462. None,
  3463. AuthorityType::FreezeAccount,
  3464. &owner2_key,
  3465. &[],
  3466. )
  3467. .unwrap(),
  3468. vec![&mut mint2_account, &mut owner2_account],
  3469. )
  3470. .unwrap();
  3471. assert_eq!(
  3472. Err(TokenError::MintCannotFreeze.into()),
  3473. do_process_instruction(
  3474. set_authority(
  3475. &program_id,
  3476. &mint2_key,
  3477. Some(&owner2_key),
  3478. AuthorityType::FreezeAccount,
  3479. &owner_key,
  3480. &[],
  3481. )
  3482. .unwrap(),
  3483. vec![&mut mint2_account, &mut owner2_account],
  3484. )
  3485. );
  3486. }
  3487. #[test]
  3488. fn test_mint_to_dups() {
  3489. let program_id = crate::id();
  3490. let account1_key = Pubkey::new_unique();
  3491. let mut account1_account = SolanaAccount::new(
  3492. account_minimum_balance(),
  3493. Account::get_packed_len(),
  3494. &program_id,
  3495. );
  3496. let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
  3497. let owner_key = Pubkey::new_unique();
  3498. let mut owner_account = SolanaAccount::default();
  3499. let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
  3500. let mint_key = Pubkey::new_unique();
  3501. let mut mint_account =
  3502. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  3503. let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
  3504. let rent_key = rent::id();
  3505. let mut rent_sysvar = rent_sysvar();
  3506. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  3507. // create mint
  3508. do_process_instruction_dups(
  3509. initialize_mint(&program_id, &mint_key, &mint_key, None, 2).unwrap(),
  3510. vec![mint_info.clone(), rent_info.clone()],
  3511. )
  3512. .unwrap();
  3513. // create account
  3514. do_process_instruction_dups(
  3515. initialize_account(&program_id, &account1_key, &mint_key, &owner_key).unwrap(),
  3516. vec![
  3517. account1_info.clone(),
  3518. mint_info.clone(),
  3519. owner_info.clone(),
  3520. rent_info.clone(),
  3521. ],
  3522. )
  3523. .unwrap();
  3524. // mint_to when mint_authority is self
  3525. do_process_instruction_dups(
  3526. mint_to(&program_id, &mint_key, &account1_key, &mint_key, &[], 42).unwrap(),
  3527. vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
  3528. )
  3529. .unwrap();
  3530. // mint_to_checked when mint_authority is self
  3531. do_process_instruction_dups(
  3532. mint_to_checked(&program_id, &mint_key, &account1_key, &mint_key, &[], 42, 2).unwrap(),
  3533. vec![mint_info.clone(), account1_info.clone(), mint_info.clone()],
  3534. )
  3535. .unwrap();
  3536. // mint_to when mint_authority is account owner
  3537. let mut mint = Mint::unpack_unchecked(&mint_info.data.borrow()).unwrap();
  3538. mint.mint_authority = COption::Some(account1_key);
  3539. Mint::pack(mint, &mut mint_info.data.borrow_mut()).unwrap();
  3540. do_process_instruction_dups(
  3541. mint_to(
  3542. &program_id,
  3543. &mint_key,
  3544. &account1_key,
  3545. &account1_key,
  3546. &[],
  3547. 42,
  3548. )
  3549. .unwrap(),
  3550. vec![
  3551. mint_info.clone(),
  3552. account1_info.clone(),
  3553. account1_info.clone(),
  3554. ],
  3555. )
  3556. .unwrap();
  3557. // mint_to_checked when mint_authority is account owner
  3558. do_process_instruction_dups(
  3559. mint_to(
  3560. &program_id,
  3561. &mint_key,
  3562. &account1_key,
  3563. &account1_key,
  3564. &[],
  3565. 42,
  3566. )
  3567. .unwrap(),
  3568. vec![
  3569. mint_info.clone(),
  3570. account1_info.clone(),
  3571. account1_info.clone(),
  3572. ],
  3573. )
  3574. .unwrap();
  3575. }
  3576. #[test]
  3577. fn test_mint_to() {
  3578. let program_id = crate::id();
  3579. let account_key = Pubkey::new_unique();
  3580. let mut account_account = SolanaAccount::new(
  3581. account_minimum_balance(),
  3582. Account::get_packed_len(),
  3583. &program_id,
  3584. );
  3585. let account2_key = Pubkey::new_unique();
  3586. let mut account2_account = SolanaAccount::new(
  3587. account_minimum_balance(),
  3588. Account::get_packed_len(),
  3589. &program_id,
  3590. );
  3591. let account3_key = Pubkey::new_unique();
  3592. let mut account3_account = SolanaAccount::new(
  3593. account_minimum_balance(),
  3594. Account::get_packed_len(),
  3595. &program_id,
  3596. );
  3597. let mismatch_key = Pubkey::new_unique();
  3598. let mut mismatch_account = SolanaAccount::new(
  3599. account_minimum_balance(),
  3600. Account::get_packed_len(),
  3601. &program_id,
  3602. );
  3603. let owner_key = Pubkey::new_unique();
  3604. let mut owner_account = SolanaAccount::default();
  3605. let owner2_key = Pubkey::new_unique();
  3606. let mut owner2_account = SolanaAccount::default();
  3607. let mint_key = Pubkey::new_unique();
  3608. let mut mint_account =
  3609. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  3610. let mint2_key = Pubkey::new_unique();
  3611. let uninitialized_key = Pubkey::new_unique();
  3612. let mut uninitialized_account = SolanaAccount::new(
  3613. account_minimum_balance(),
  3614. Account::get_packed_len(),
  3615. &program_id,
  3616. );
  3617. let mut rent_sysvar = rent_sysvar();
  3618. // create new mint with owner
  3619. do_process_instruction(
  3620. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  3621. vec![&mut mint_account, &mut rent_sysvar],
  3622. )
  3623. .unwrap();
  3624. // create account
  3625. do_process_instruction(
  3626. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  3627. vec![
  3628. &mut account_account,
  3629. &mut mint_account,
  3630. &mut owner_account,
  3631. &mut rent_sysvar,
  3632. ],
  3633. )
  3634. .unwrap();
  3635. // create another account
  3636. do_process_instruction(
  3637. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  3638. vec![
  3639. &mut account2_account,
  3640. &mut mint_account,
  3641. &mut owner_account,
  3642. &mut rent_sysvar,
  3643. ],
  3644. )
  3645. .unwrap();
  3646. // create another account
  3647. do_process_instruction(
  3648. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  3649. vec![
  3650. &mut account3_account,
  3651. &mut mint_account,
  3652. &mut owner_account,
  3653. &mut rent_sysvar,
  3654. ],
  3655. )
  3656. .unwrap();
  3657. // create mismatch account
  3658. do_process_instruction(
  3659. initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
  3660. vec![
  3661. &mut mismatch_account,
  3662. &mut mint_account,
  3663. &mut owner_account,
  3664. &mut rent_sysvar,
  3665. ],
  3666. )
  3667. .unwrap();
  3668. let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
  3669. account.mint = mint2_key;
  3670. Account::pack(account, &mut mismatch_account.data).unwrap();
  3671. // mint to
  3672. do_process_instruction(
  3673. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
  3674. vec![&mut mint_account, &mut account_account, &mut owner_account],
  3675. )
  3676. .unwrap();
  3677. let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
  3678. assert_eq!(mint.supply, 42);
  3679. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  3680. assert_eq!(account.amount, 42);
  3681. // mint to another account to test supply accumulation
  3682. do_process_instruction(
  3683. mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
  3684. vec![&mut mint_account, &mut account2_account, &mut owner_account],
  3685. )
  3686. .unwrap();
  3687. let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
  3688. assert_eq!(mint.supply, 84);
  3689. let account = Account::unpack_unchecked(&account2_account.data).unwrap();
  3690. assert_eq!(account.amount, 42);
  3691. // missing signer
  3692. let mut instruction =
  3693. mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
  3694. instruction.accounts[2].is_signer = false;
  3695. assert_eq!(
  3696. Err(ProgramError::MissingRequiredSignature),
  3697. do_process_instruction(
  3698. instruction,
  3699. vec![&mut mint_account, &mut account2_account, &mut owner_account],
  3700. )
  3701. );
  3702. // mismatch account
  3703. assert_eq!(
  3704. Err(TokenError::MintMismatch.into()),
  3705. do_process_instruction(
  3706. mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
  3707. vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
  3708. )
  3709. );
  3710. // missing owner
  3711. assert_eq!(
  3712. Err(TokenError::OwnerMismatch.into()),
  3713. do_process_instruction(
  3714. mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
  3715. vec![
  3716. &mut mint_account,
  3717. &mut account2_account,
  3718. &mut owner2_account,
  3719. ],
  3720. )
  3721. );
  3722. // mint not owned by program
  3723. let not_program_id = Pubkey::new_unique();
  3724. mint_account.owner = not_program_id;
  3725. assert_eq!(
  3726. Err(ProgramError::IncorrectProgramId),
  3727. do_process_instruction(
  3728. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
  3729. vec![&mut mint_account, &mut account_account, &mut owner_account],
  3730. )
  3731. );
  3732. mint_account.owner = program_id;
  3733. // account not owned by program
  3734. let not_program_id = Pubkey::new_unique();
  3735. account_account.owner = not_program_id;
  3736. assert_eq!(
  3737. Err(ProgramError::IncorrectProgramId),
  3738. do_process_instruction(
  3739. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 0).unwrap(),
  3740. vec![&mut mint_account, &mut account_account, &mut owner_account],
  3741. )
  3742. );
  3743. account_account.owner = program_id;
  3744. // uninitialized destination account
  3745. assert_eq!(
  3746. Err(ProgramError::UninitializedAccount),
  3747. do_process_instruction(
  3748. mint_to(
  3749. &program_id,
  3750. &mint_key,
  3751. &uninitialized_key,
  3752. &owner_key,
  3753. &[],
  3754. 42
  3755. )
  3756. .unwrap(),
  3757. vec![
  3758. &mut mint_account,
  3759. &mut uninitialized_account,
  3760. &mut owner_account,
  3761. ],
  3762. )
  3763. );
  3764. // unset mint_authority and test minting fails
  3765. do_process_instruction(
  3766. set_authority(
  3767. &program_id,
  3768. &mint_key,
  3769. None,
  3770. AuthorityType::MintTokens,
  3771. &owner_key,
  3772. &[],
  3773. )
  3774. .unwrap(),
  3775. vec![&mut mint_account, &mut owner_account],
  3776. )
  3777. .unwrap();
  3778. assert_eq!(
  3779. Err(TokenError::FixedSupply.into()),
  3780. do_process_instruction(
  3781. mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
  3782. vec![&mut mint_account, &mut account2_account, &mut owner_account],
  3783. )
  3784. );
  3785. }
  3786. #[test]
  3787. fn test_burn_dups() {
  3788. let program_id = crate::id();
  3789. let account1_key = Pubkey::new_unique();
  3790. let mut account1_account = SolanaAccount::new(
  3791. account_minimum_balance(),
  3792. Account::get_packed_len(),
  3793. &program_id,
  3794. );
  3795. let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
  3796. let owner_key = Pubkey::new_unique();
  3797. let mut owner_account = SolanaAccount::default();
  3798. let owner_info: AccountInfo = (&owner_key, true, &mut owner_account).into();
  3799. let mint_key = Pubkey::new_unique();
  3800. let mut mint_account =
  3801. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  3802. let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
  3803. let rent_key = rent::id();
  3804. let mut rent_sysvar = rent_sysvar();
  3805. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  3806. // create mint
  3807. do_process_instruction_dups(
  3808. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  3809. vec![mint_info.clone(), rent_info.clone()],
  3810. )
  3811. .unwrap();
  3812. // create account
  3813. do_process_instruction_dups(
  3814. initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
  3815. vec![
  3816. account1_info.clone(),
  3817. mint_info.clone(),
  3818. account1_info.clone(),
  3819. rent_info.clone(),
  3820. ],
  3821. )
  3822. .unwrap();
  3823. // mint to account
  3824. do_process_instruction_dups(
  3825. mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
  3826. vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
  3827. )
  3828. .unwrap();
  3829. // source-owner burn
  3830. do_process_instruction_dups(
  3831. burn(
  3832. &program_id,
  3833. &mint_key,
  3834. &account1_key,
  3835. &account1_key,
  3836. &[],
  3837. 500,
  3838. )
  3839. .unwrap(),
  3840. vec![
  3841. account1_info.clone(),
  3842. mint_info.clone(),
  3843. account1_info.clone(),
  3844. ],
  3845. )
  3846. .unwrap();
  3847. // source-owner burn_checked
  3848. do_process_instruction_dups(
  3849. burn_checked(
  3850. &program_id,
  3851. &account1_key,
  3852. &mint_key,
  3853. &account1_key,
  3854. &[],
  3855. 500,
  3856. 2,
  3857. )
  3858. .unwrap(),
  3859. vec![
  3860. account1_info.clone(),
  3861. mint_info.clone(),
  3862. account1_info.clone(),
  3863. ],
  3864. )
  3865. .unwrap();
  3866. // mint-owner burn
  3867. do_process_instruction_dups(
  3868. mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
  3869. vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
  3870. )
  3871. .unwrap();
  3872. let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
  3873. account.owner = mint_key;
  3874. Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
  3875. do_process_instruction_dups(
  3876. burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
  3877. vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
  3878. )
  3879. .unwrap();
  3880. // mint-owner burn_checked
  3881. do_process_instruction_dups(
  3882. burn_checked(
  3883. &program_id,
  3884. &account1_key,
  3885. &mint_key,
  3886. &mint_key,
  3887. &[],
  3888. 500,
  3889. 2,
  3890. )
  3891. .unwrap(),
  3892. vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
  3893. )
  3894. .unwrap();
  3895. // source-delegate burn
  3896. do_process_instruction_dups(
  3897. mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
  3898. vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
  3899. )
  3900. .unwrap();
  3901. let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
  3902. account.delegated_amount = 1000;
  3903. account.delegate = COption::Some(account1_key);
  3904. account.owner = owner_key;
  3905. Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
  3906. do_process_instruction_dups(
  3907. burn(
  3908. &program_id,
  3909. &account1_key,
  3910. &mint_key,
  3911. &account1_key,
  3912. &[],
  3913. 500,
  3914. )
  3915. .unwrap(),
  3916. vec![
  3917. account1_info.clone(),
  3918. mint_info.clone(),
  3919. account1_info.clone(),
  3920. ],
  3921. )
  3922. .unwrap();
  3923. // source-delegate burn_checked
  3924. do_process_instruction_dups(
  3925. burn_checked(
  3926. &program_id,
  3927. &account1_key,
  3928. &mint_key,
  3929. &account1_key,
  3930. &[],
  3931. 500,
  3932. 2,
  3933. )
  3934. .unwrap(),
  3935. vec![
  3936. account1_info.clone(),
  3937. mint_info.clone(),
  3938. account1_info.clone(),
  3939. ],
  3940. )
  3941. .unwrap();
  3942. // mint-delegate burn
  3943. do_process_instruction_dups(
  3944. mint_to(&program_id, &mint_key, &account1_key, &owner_key, &[], 1000).unwrap(),
  3945. vec![mint_info.clone(), account1_info.clone(), owner_info.clone()],
  3946. )
  3947. .unwrap();
  3948. let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
  3949. account.delegated_amount = 1000;
  3950. account.delegate = COption::Some(mint_key);
  3951. account.owner = owner_key;
  3952. Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
  3953. do_process_instruction_dups(
  3954. burn(&program_id, &account1_key, &mint_key, &mint_key, &[], 500).unwrap(),
  3955. vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
  3956. )
  3957. .unwrap();
  3958. // mint-delegate burn_checked
  3959. do_process_instruction_dups(
  3960. burn_checked(
  3961. &program_id,
  3962. &account1_key,
  3963. &mint_key,
  3964. &mint_key,
  3965. &[],
  3966. 500,
  3967. 2,
  3968. )
  3969. .unwrap(),
  3970. vec![account1_info.clone(), mint_info.clone(), mint_info.clone()],
  3971. )
  3972. .unwrap();
  3973. }
  3974. #[test]
  3975. fn test_burn() {
  3976. let program_id = crate::id();
  3977. let account_key = Pubkey::new_unique();
  3978. let mut account_account = SolanaAccount::new(
  3979. account_minimum_balance(),
  3980. Account::get_packed_len(),
  3981. &program_id,
  3982. );
  3983. let account2_key = Pubkey::new_unique();
  3984. let mut account2_account = SolanaAccount::new(
  3985. account_minimum_balance(),
  3986. Account::get_packed_len(),
  3987. &program_id,
  3988. );
  3989. let account3_key = Pubkey::new_unique();
  3990. let mut account3_account = SolanaAccount::new(
  3991. account_minimum_balance(),
  3992. Account::get_packed_len(),
  3993. &program_id,
  3994. );
  3995. let delegate_key = Pubkey::new_unique();
  3996. let mut delegate_account = SolanaAccount::default();
  3997. let mismatch_key = Pubkey::new_unique();
  3998. let mut mismatch_account = SolanaAccount::new(
  3999. account_minimum_balance(),
  4000. Account::get_packed_len(),
  4001. &program_id,
  4002. );
  4003. let owner_key = Pubkey::new_unique();
  4004. let mut owner_account = SolanaAccount::default();
  4005. let owner2_key = Pubkey::new_unique();
  4006. let mut owner2_account = SolanaAccount::default();
  4007. let mint_key = Pubkey::new_unique();
  4008. let mut mint_account =
  4009. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  4010. let mint2_key = Pubkey::new_unique();
  4011. let mut rent_sysvar = rent_sysvar();
  4012. // create new mint
  4013. do_process_instruction(
  4014. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  4015. vec![&mut mint_account, &mut rent_sysvar],
  4016. )
  4017. .unwrap();
  4018. // create account
  4019. do_process_instruction(
  4020. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  4021. vec![
  4022. &mut account_account,
  4023. &mut mint_account,
  4024. &mut owner_account,
  4025. &mut rent_sysvar,
  4026. ],
  4027. )
  4028. .unwrap();
  4029. // create another account
  4030. do_process_instruction(
  4031. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  4032. vec![
  4033. &mut account2_account,
  4034. &mut mint_account,
  4035. &mut owner_account,
  4036. &mut rent_sysvar,
  4037. ],
  4038. )
  4039. .unwrap();
  4040. // create another account
  4041. do_process_instruction(
  4042. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  4043. vec![
  4044. &mut account3_account,
  4045. &mut mint_account,
  4046. &mut owner_account,
  4047. &mut rent_sysvar,
  4048. ],
  4049. )
  4050. .unwrap();
  4051. // create mismatch account
  4052. do_process_instruction(
  4053. initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
  4054. vec![
  4055. &mut mismatch_account,
  4056. &mut mint_account,
  4057. &mut owner_account,
  4058. &mut rent_sysvar,
  4059. ],
  4060. )
  4061. .unwrap();
  4062. // mint to account
  4063. do_process_instruction(
  4064. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  4065. vec![&mut mint_account, &mut account_account, &mut owner_account],
  4066. )
  4067. .unwrap();
  4068. // mint to mismatch account and change mint key
  4069. do_process_instruction(
  4070. mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 1000).unwrap(),
  4071. vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
  4072. )
  4073. .unwrap();
  4074. let mut account = Account::unpack_unchecked(&mismatch_account.data).unwrap();
  4075. account.mint = mint2_key;
  4076. Account::pack(account, &mut mismatch_account.data).unwrap();
  4077. // missing signer
  4078. let mut instruction =
  4079. burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
  4080. instruction.accounts[1].is_signer = false;
  4081. assert_eq!(
  4082. Err(TokenError::OwnerMismatch.into()),
  4083. do_process_instruction(
  4084. instruction,
  4085. vec![
  4086. &mut account_account,
  4087. &mut mint_account,
  4088. &mut delegate_account
  4089. ],
  4090. )
  4091. );
  4092. // missing owner
  4093. assert_eq!(
  4094. Err(TokenError::OwnerMismatch.into()),
  4095. do_process_instruction(
  4096. burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
  4097. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  4098. )
  4099. );
  4100. // account not owned by program
  4101. let not_program_id = Pubkey::new_unique();
  4102. account_account.owner = not_program_id;
  4103. assert_eq!(
  4104. Err(ProgramError::IncorrectProgramId),
  4105. do_process_instruction(
  4106. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
  4107. vec![&mut account_account, &mut mint_account, &mut owner_account],
  4108. )
  4109. );
  4110. account_account.owner = program_id;
  4111. // mint not owned by program
  4112. let not_program_id = Pubkey::new_unique();
  4113. mint_account.owner = not_program_id;
  4114. assert_eq!(
  4115. Err(ProgramError::IncorrectProgramId),
  4116. do_process_instruction(
  4117. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 0).unwrap(),
  4118. vec![&mut account_account, &mut mint_account, &mut owner_account],
  4119. )
  4120. );
  4121. mint_account.owner = program_id;
  4122. // mint mismatch
  4123. assert_eq!(
  4124. Err(TokenError::MintMismatch.into()),
  4125. do_process_instruction(
  4126. burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
  4127. vec![&mut mismatch_account, &mut mint_account, &mut owner_account],
  4128. )
  4129. );
  4130. // burn
  4131. do_process_instruction(
  4132. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 21).unwrap(),
  4133. vec![&mut account_account, &mut mint_account, &mut owner_account],
  4134. )
  4135. .unwrap();
  4136. // burn_checked, with incorrect decimals
  4137. assert_eq!(
  4138. Err(TokenError::MintDecimalsMismatch.into()),
  4139. do_process_instruction(
  4140. burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 3).unwrap(),
  4141. vec![&mut account_account, &mut mint_account, &mut owner_account],
  4142. )
  4143. );
  4144. // burn_checked
  4145. do_process_instruction(
  4146. burn_checked(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 2).unwrap(),
  4147. vec![&mut account_account, &mut mint_account, &mut owner_account],
  4148. )
  4149. .unwrap();
  4150. let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
  4151. assert_eq!(mint.supply, 2000 - 42);
  4152. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  4153. assert_eq!(account.amount, 1000 - 42);
  4154. // insufficient funds
  4155. assert_eq!(
  4156. Err(TokenError::InsufficientFunds.into()),
  4157. do_process_instruction(
  4158. burn(
  4159. &program_id,
  4160. &account_key,
  4161. &mint_key,
  4162. &owner_key,
  4163. &[],
  4164. 100_000_000
  4165. )
  4166. .unwrap(),
  4167. vec![&mut account_account, &mut mint_account, &mut owner_account],
  4168. )
  4169. );
  4170. // approve delegate
  4171. do_process_instruction(
  4172. approve(
  4173. &program_id,
  4174. &account_key,
  4175. &delegate_key,
  4176. &owner_key,
  4177. &[],
  4178. 84,
  4179. )
  4180. .unwrap(),
  4181. vec![
  4182. &mut account_account,
  4183. &mut delegate_account,
  4184. &mut owner_account,
  4185. ],
  4186. )
  4187. .unwrap();
  4188. // not a delegate of source account
  4189. assert_eq!(
  4190. Err(TokenError::OwnerMismatch.into()),
  4191. do_process_instruction(
  4192. burn(
  4193. &program_id,
  4194. &account_key,
  4195. &mint_key,
  4196. &owner2_key, // <-- incorrect owner or delegate
  4197. &[],
  4198. 1,
  4199. )
  4200. .unwrap(),
  4201. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  4202. )
  4203. );
  4204. // insufficient funds approved via delegate
  4205. assert_eq!(
  4206. Err(TokenError::InsufficientFunds.into()),
  4207. do_process_instruction(
  4208. burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 85).unwrap(),
  4209. vec![
  4210. &mut account_account,
  4211. &mut mint_account,
  4212. &mut delegate_account
  4213. ],
  4214. )
  4215. );
  4216. // burn via delegate
  4217. do_process_instruction(
  4218. burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
  4219. vec![
  4220. &mut account_account,
  4221. &mut mint_account,
  4222. &mut delegate_account,
  4223. ],
  4224. )
  4225. .unwrap();
  4226. // match
  4227. let mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
  4228. assert_eq!(mint.supply, 2000 - 42 - 84);
  4229. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  4230. assert_eq!(account.amount, 1000 - 42 - 84);
  4231. // insufficient funds approved via delegate
  4232. assert_eq!(
  4233. Err(TokenError::OwnerMismatch.into()),
  4234. do_process_instruction(
  4235. burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 1).unwrap(),
  4236. vec![
  4237. &mut account_account,
  4238. &mut mint_account,
  4239. &mut delegate_account
  4240. ],
  4241. )
  4242. );
  4243. }
  4244. #[test]
  4245. fn test_burn_and_close_system_and_incinerator_tokens() {
  4246. let program_id = crate::id();
  4247. let account_key = Pubkey::new_unique();
  4248. let mut account_account = SolanaAccount::new(
  4249. account_minimum_balance(),
  4250. Account::get_packed_len(),
  4251. &program_id,
  4252. );
  4253. let incinerator_account_key = Pubkey::new_unique();
  4254. let mut incinerator_account = SolanaAccount::new(
  4255. account_minimum_balance(),
  4256. Account::get_packed_len(),
  4257. &program_id,
  4258. );
  4259. let system_account_key = Pubkey::new_unique();
  4260. let mut system_account = SolanaAccount::new(
  4261. account_minimum_balance(),
  4262. Account::get_packed_len(),
  4263. &program_id,
  4264. );
  4265. let owner_key = Pubkey::new_unique();
  4266. let mut owner_account = SolanaAccount::default();
  4267. let recipient_key = Pubkey::new_unique();
  4268. let mut recipient_account = SolanaAccount::default();
  4269. let mut mock_incinerator_account = SolanaAccount::default();
  4270. let mint_key = Pubkey::new_unique();
  4271. let mut mint_account =
  4272. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  4273. // create new mint
  4274. do_process_instruction(
  4275. initialize_mint2(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  4276. vec![&mut mint_account],
  4277. )
  4278. .unwrap();
  4279. // create account
  4280. do_process_instruction(
  4281. initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  4282. vec![&mut account_account, &mut mint_account],
  4283. )
  4284. .unwrap();
  4285. // create incinerator- and system-owned accounts
  4286. do_process_instruction(
  4287. initialize_account3(
  4288. &program_id,
  4289. &incinerator_account_key,
  4290. &mint_key,
  4291. &solana_program::incinerator::id(),
  4292. )
  4293. .unwrap(),
  4294. vec![&mut incinerator_account, &mut mint_account],
  4295. )
  4296. .unwrap();
  4297. do_process_instruction(
  4298. initialize_account3(
  4299. &program_id,
  4300. &system_account_key,
  4301. &mint_key,
  4302. &solana_program::system_program::id(),
  4303. )
  4304. .unwrap(),
  4305. vec![&mut system_account, &mut mint_account],
  4306. )
  4307. .unwrap();
  4308. // mint to account
  4309. do_process_instruction(
  4310. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  4311. vec![&mut mint_account, &mut account_account, &mut owner_account],
  4312. )
  4313. .unwrap();
  4314. // transfer half to incinerator, half to system program
  4315. do_process_instruction(
  4316. transfer(
  4317. &program_id,
  4318. &account_key,
  4319. &incinerator_account_key,
  4320. &owner_key,
  4321. &[],
  4322. 500,
  4323. )
  4324. .unwrap(),
  4325. vec![
  4326. &mut account_account,
  4327. &mut incinerator_account,
  4328. &mut owner_account,
  4329. ],
  4330. )
  4331. .unwrap();
  4332. do_process_instruction(
  4333. transfer(
  4334. &program_id,
  4335. &account_key,
  4336. &system_account_key,
  4337. &owner_key,
  4338. &[],
  4339. 500,
  4340. )
  4341. .unwrap(),
  4342. vec![
  4343. &mut account_account,
  4344. &mut system_account,
  4345. &mut owner_account,
  4346. ],
  4347. )
  4348. .unwrap();
  4349. // close with balance fails
  4350. assert_eq!(
  4351. Err(TokenError::NonNativeHasBalance.into()),
  4352. do_process_instruction(
  4353. close_account(
  4354. &program_id,
  4355. &incinerator_account_key,
  4356. &solana_program::incinerator::id(),
  4357. &owner_key,
  4358. &[]
  4359. )
  4360. .unwrap(),
  4361. vec![
  4362. &mut incinerator_account,
  4363. &mut mock_incinerator_account,
  4364. &mut owner_account,
  4365. ],
  4366. )
  4367. );
  4368. assert_eq!(
  4369. Err(TokenError::NonNativeHasBalance.into()),
  4370. do_process_instruction(
  4371. close_account(
  4372. &program_id,
  4373. &system_account_key,
  4374. &solana_program::incinerator::id(),
  4375. &owner_key,
  4376. &[]
  4377. )
  4378. .unwrap(),
  4379. vec![
  4380. &mut system_account,
  4381. &mut mock_incinerator_account,
  4382. &mut owner_account,
  4383. ],
  4384. )
  4385. );
  4386. // anyone can burn
  4387. do_process_instruction(
  4388. burn(
  4389. &program_id,
  4390. &incinerator_account_key,
  4391. &mint_key,
  4392. &recipient_key,
  4393. &[],
  4394. 500,
  4395. )
  4396. .unwrap(),
  4397. vec![
  4398. &mut incinerator_account,
  4399. &mut mint_account,
  4400. &mut recipient_account,
  4401. ],
  4402. )
  4403. .unwrap();
  4404. do_process_instruction(
  4405. burn(
  4406. &program_id,
  4407. &system_account_key,
  4408. &mint_key,
  4409. &recipient_key,
  4410. &[],
  4411. 500,
  4412. )
  4413. .unwrap(),
  4414. vec![
  4415. &mut system_account,
  4416. &mut mint_account,
  4417. &mut recipient_account,
  4418. ],
  4419. )
  4420. .unwrap();
  4421. // closing fails if destination is not the incinerator
  4422. assert_eq!(
  4423. Err(ProgramError::InvalidAccountData),
  4424. do_process_instruction(
  4425. close_account(
  4426. &program_id,
  4427. &incinerator_account_key,
  4428. &recipient_key,
  4429. &owner_key,
  4430. &[]
  4431. )
  4432. .unwrap(),
  4433. vec![
  4434. &mut incinerator_account,
  4435. &mut recipient_account,
  4436. &mut owner_account,
  4437. ],
  4438. )
  4439. );
  4440. assert_eq!(
  4441. Err(ProgramError::InvalidAccountData),
  4442. do_process_instruction(
  4443. close_account(
  4444. &program_id,
  4445. &system_account_key,
  4446. &recipient_key,
  4447. &owner_key,
  4448. &[]
  4449. )
  4450. .unwrap(),
  4451. vec![
  4452. &mut system_account,
  4453. &mut recipient_account,
  4454. &mut owner_account,
  4455. ],
  4456. )
  4457. );
  4458. // closing succeeds with incinerator recipient
  4459. do_process_instruction(
  4460. close_account(
  4461. &program_id,
  4462. &incinerator_account_key,
  4463. &solana_program::incinerator::id(),
  4464. &owner_key,
  4465. &[],
  4466. )
  4467. .unwrap(),
  4468. vec![
  4469. &mut incinerator_account,
  4470. &mut mock_incinerator_account,
  4471. &mut owner_account,
  4472. ],
  4473. )
  4474. .unwrap();
  4475. do_process_instruction(
  4476. close_account(
  4477. &program_id,
  4478. &system_account_key,
  4479. &solana_program::incinerator::id(),
  4480. &owner_key,
  4481. &[],
  4482. )
  4483. .unwrap(),
  4484. vec![
  4485. &mut system_account,
  4486. &mut mock_incinerator_account,
  4487. &mut owner_account,
  4488. ],
  4489. )
  4490. .unwrap();
  4491. }
  4492. #[test]
  4493. fn test_multisig() {
  4494. let program_id = crate::id();
  4495. let mint_key = Pubkey::new_unique();
  4496. let mut mint_account =
  4497. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  4498. let account_key = Pubkey::new_unique();
  4499. let mut account = SolanaAccount::new(
  4500. account_minimum_balance(),
  4501. Account::get_packed_len(),
  4502. &program_id,
  4503. );
  4504. let account2_key = Pubkey::new_unique();
  4505. let mut account2_account = SolanaAccount::new(
  4506. account_minimum_balance(),
  4507. Account::get_packed_len(),
  4508. &program_id,
  4509. );
  4510. let owner_key = Pubkey::new_unique();
  4511. let mut owner_account = SolanaAccount::default();
  4512. let multisig_key = Pubkey::new_unique();
  4513. let mut multisig_account = SolanaAccount::new(42, Multisig::get_packed_len(), &program_id);
  4514. let multisig_delegate_key = Pubkey::new_unique();
  4515. let mut multisig_delegate_account = SolanaAccount::new(
  4516. multisig_minimum_balance(),
  4517. Multisig::get_packed_len(),
  4518. &program_id,
  4519. );
  4520. let signer_keys = vec![Pubkey::new_unique(); MAX_SIGNERS];
  4521. let signer_key_refs: Vec<&Pubkey> = signer_keys.iter().collect();
  4522. let mut signer_accounts = vec![SolanaAccount::new(0, 0, &program_id); MAX_SIGNERS];
  4523. let mut rent_sysvar = rent_sysvar();
  4524. // multisig is not rent exempt
  4525. let account_info_iter = &mut signer_accounts.iter_mut();
  4526. assert_eq!(
  4527. Err(TokenError::NotRentExempt.into()),
  4528. do_process_instruction(
  4529. initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
  4530. vec![
  4531. &mut multisig_account,
  4532. &mut rent_sysvar,
  4533. account_info_iter.next().unwrap(),
  4534. ],
  4535. )
  4536. );
  4537. multisig_account.lamports = multisig_minimum_balance();
  4538. let mut multisig_account2 = multisig_account.clone();
  4539. // single signer
  4540. let account_info_iter = &mut signer_accounts.iter_mut();
  4541. do_process_instruction(
  4542. initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
  4543. vec![
  4544. &mut multisig_account,
  4545. &mut rent_sysvar,
  4546. account_info_iter.next().unwrap(),
  4547. ],
  4548. )
  4549. .unwrap();
  4550. // single signer using `initialize_multisig2`
  4551. let account_info_iter = &mut signer_accounts.iter_mut();
  4552. do_process_instruction(
  4553. initialize_multisig2(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
  4554. vec![&mut multisig_account2, account_info_iter.next().unwrap()],
  4555. )
  4556. .unwrap();
  4557. // multiple signer
  4558. let account_info_iter = &mut signer_accounts.iter_mut();
  4559. do_process_instruction(
  4560. initialize_multisig(
  4561. &program_id,
  4562. &multisig_delegate_key,
  4563. &signer_key_refs,
  4564. MAX_SIGNERS as u8,
  4565. )
  4566. .unwrap(),
  4567. vec![
  4568. &mut multisig_delegate_account,
  4569. &mut rent_sysvar,
  4570. account_info_iter.next().unwrap(),
  4571. account_info_iter.next().unwrap(),
  4572. account_info_iter.next().unwrap(),
  4573. account_info_iter.next().unwrap(),
  4574. account_info_iter.next().unwrap(),
  4575. account_info_iter.next().unwrap(),
  4576. account_info_iter.next().unwrap(),
  4577. account_info_iter.next().unwrap(),
  4578. account_info_iter.next().unwrap(),
  4579. account_info_iter.next().unwrap(),
  4580. account_info_iter.next().unwrap(),
  4581. ],
  4582. )
  4583. .unwrap();
  4584. // create new mint with multisig owner
  4585. do_process_instruction(
  4586. initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
  4587. vec![&mut mint_account, &mut rent_sysvar],
  4588. )
  4589. .unwrap();
  4590. // create account with multisig owner
  4591. do_process_instruction(
  4592. initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
  4593. vec![
  4594. &mut account,
  4595. &mut mint_account,
  4596. &mut multisig_account,
  4597. &mut rent_sysvar,
  4598. ],
  4599. )
  4600. .unwrap();
  4601. // create another account with multisig owner
  4602. do_process_instruction(
  4603. initialize_account(
  4604. &program_id,
  4605. &account2_key,
  4606. &mint_key,
  4607. &multisig_delegate_key,
  4608. )
  4609. .unwrap(),
  4610. vec![
  4611. &mut account2_account,
  4612. &mut mint_account,
  4613. &mut multisig_account,
  4614. &mut rent_sysvar,
  4615. ],
  4616. )
  4617. .unwrap();
  4618. // mint to account
  4619. let account_info_iter = &mut signer_accounts.iter_mut();
  4620. do_process_instruction(
  4621. mint_to(
  4622. &program_id,
  4623. &mint_key,
  4624. &account_key,
  4625. &multisig_key,
  4626. &[&signer_keys[0]],
  4627. 1000,
  4628. )
  4629. .unwrap(),
  4630. vec![
  4631. &mut mint_account,
  4632. &mut account,
  4633. &mut multisig_account,
  4634. account_info_iter.next().unwrap(),
  4635. ],
  4636. )
  4637. .unwrap();
  4638. // approve
  4639. let account_info_iter = &mut signer_accounts.iter_mut();
  4640. do_process_instruction(
  4641. approve(
  4642. &program_id,
  4643. &account_key,
  4644. &multisig_delegate_key,
  4645. &multisig_key,
  4646. &[&signer_keys[0]],
  4647. 100,
  4648. )
  4649. .unwrap(),
  4650. vec![
  4651. &mut account,
  4652. &mut multisig_delegate_account,
  4653. &mut multisig_account,
  4654. account_info_iter.next().unwrap(),
  4655. ],
  4656. )
  4657. .unwrap();
  4658. // transfer
  4659. let account_info_iter = &mut signer_accounts.iter_mut();
  4660. do_process_instruction(
  4661. transfer(
  4662. &program_id,
  4663. &account_key,
  4664. &account2_key,
  4665. &multisig_key,
  4666. &[&signer_keys[0]],
  4667. 42,
  4668. )
  4669. .unwrap(),
  4670. vec![
  4671. &mut account,
  4672. &mut account2_account,
  4673. &mut multisig_account,
  4674. account_info_iter.next().unwrap(),
  4675. ],
  4676. )
  4677. .unwrap();
  4678. // transfer via delegate
  4679. let account_info_iter = &mut signer_accounts.iter_mut();
  4680. do_process_instruction(
  4681. transfer(
  4682. &program_id,
  4683. &account_key,
  4684. &account2_key,
  4685. &multisig_delegate_key,
  4686. &signer_key_refs,
  4687. 42,
  4688. )
  4689. .unwrap(),
  4690. vec![
  4691. &mut account,
  4692. &mut account2_account,
  4693. &mut multisig_delegate_account,
  4694. account_info_iter.next().unwrap(),
  4695. account_info_iter.next().unwrap(),
  4696. account_info_iter.next().unwrap(),
  4697. account_info_iter.next().unwrap(),
  4698. account_info_iter.next().unwrap(),
  4699. account_info_iter.next().unwrap(),
  4700. account_info_iter.next().unwrap(),
  4701. account_info_iter.next().unwrap(),
  4702. account_info_iter.next().unwrap(),
  4703. account_info_iter.next().unwrap(),
  4704. account_info_iter.next().unwrap(),
  4705. ],
  4706. )
  4707. .unwrap();
  4708. // mint to
  4709. let account_info_iter = &mut signer_accounts.iter_mut();
  4710. do_process_instruction(
  4711. mint_to(
  4712. &program_id,
  4713. &mint_key,
  4714. &account2_key,
  4715. &multisig_key,
  4716. &[&signer_keys[0]],
  4717. 42,
  4718. )
  4719. .unwrap(),
  4720. vec![
  4721. &mut mint_account,
  4722. &mut account2_account,
  4723. &mut multisig_account,
  4724. account_info_iter.next().unwrap(),
  4725. ],
  4726. )
  4727. .unwrap();
  4728. // burn
  4729. let account_info_iter = &mut signer_accounts.iter_mut();
  4730. do_process_instruction(
  4731. burn(
  4732. &program_id,
  4733. &account_key,
  4734. &mint_key,
  4735. &multisig_key,
  4736. &[&signer_keys[0]],
  4737. 42,
  4738. )
  4739. .unwrap(),
  4740. vec![
  4741. &mut account,
  4742. &mut mint_account,
  4743. &mut multisig_account,
  4744. account_info_iter.next().unwrap(),
  4745. ],
  4746. )
  4747. .unwrap();
  4748. // burn via delegate
  4749. let account_info_iter = &mut signer_accounts.iter_mut();
  4750. do_process_instruction(
  4751. burn(
  4752. &program_id,
  4753. &account_key,
  4754. &mint_key,
  4755. &multisig_delegate_key,
  4756. &signer_key_refs,
  4757. 42,
  4758. )
  4759. .unwrap(),
  4760. vec![
  4761. &mut account,
  4762. &mut mint_account,
  4763. &mut multisig_delegate_account,
  4764. account_info_iter.next().unwrap(),
  4765. account_info_iter.next().unwrap(),
  4766. account_info_iter.next().unwrap(),
  4767. account_info_iter.next().unwrap(),
  4768. account_info_iter.next().unwrap(),
  4769. account_info_iter.next().unwrap(),
  4770. account_info_iter.next().unwrap(),
  4771. account_info_iter.next().unwrap(),
  4772. account_info_iter.next().unwrap(),
  4773. account_info_iter.next().unwrap(),
  4774. account_info_iter.next().unwrap(),
  4775. ],
  4776. )
  4777. .unwrap();
  4778. // freeze account
  4779. let account3_key = Pubkey::new_unique();
  4780. let mut account3_account = SolanaAccount::new(
  4781. account_minimum_balance(),
  4782. Account::get_packed_len(),
  4783. &program_id,
  4784. );
  4785. let mint2_key = Pubkey::new_unique();
  4786. let mut mint2_account =
  4787. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  4788. do_process_instruction(
  4789. initialize_mint(
  4790. &program_id,
  4791. &mint2_key,
  4792. &multisig_key,
  4793. Some(&multisig_key),
  4794. 2,
  4795. )
  4796. .unwrap(),
  4797. vec![&mut mint2_account, &mut rent_sysvar],
  4798. )
  4799. .unwrap();
  4800. do_process_instruction(
  4801. initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
  4802. vec![
  4803. &mut account3_account,
  4804. &mut mint2_account,
  4805. &mut owner_account,
  4806. &mut rent_sysvar,
  4807. ],
  4808. )
  4809. .unwrap();
  4810. let account_info_iter = &mut signer_accounts.iter_mut();
  4811. do_process_instruction(
  4812. mint_to(
  4813. &program_id,
  4814. &mint2_key,
  4815. &account3_key,
  4816. &multisig_key,
  4817. &[&signer_keys[0]],
  4818. 1000,
  4819. )
  4820. .unwrap(),
  4821. vec![
  4822. &mut mint2_account,
  4823. &mut account3_account,
  4824. &mut multisig_account,
  4825. account_info_iter.next().unwrap(),
  4826. ],
  4827. )
  4828. .unwrap();
  4829. let account_info_iter = &mut signer_accounts.iter_mut();
  4830. do_process_instruction(
  4831. freeze_account(
  4832. &program_id,
  4833. &account3_key,
  4834. &mint2_key,
  4835. &multisig_key,
  4836. &[&signer_keys[0]],
  4837. )
  4838. .unwrap(),
  4839. vec![
  4840. &mut account3_account,
  4841. &mut mint2_account,
  4842. &mut multisig_account,
  4843. account_info_iter.next().unwrap(),
  4844. ],
  4845. )
  4846. .unwrap();
  4847. // do SetAuthority on mint
  4848. let account_info_iter = &mut signer_accounts.iter_mut();
  4849. do_process_instruction(
  4850. set_authority(
  4851. &program_id,
  4852. &mint_key,
  4853. Some(&owner_key),
  4854. AuthorityType::MintTokens,
  4855. &multisig_key,
  4856. &[&signer_keys[0]],
  4857. )
  4858. .unwrap(),
  4859. vec![
  4860. &mut mint_account,
  4861. &mut multisig_account,
  4862. account_info_iter.next().unwrap(),
  4863. ],
  4864. )
  4865. .unwrap();
  4866. // do SetAuthority on account
  4867. let account_info_iter = &mut signer_accounts.iter_mut();
  4868. do_process_instruction(
  4869. set_authority(
  4870. &program_id,
  4871. &account_key,
  4872. Some(&owner_key),
  4873. AuthorityType::AccountOwner,
  4874. &multisig_key,
  4875. &[&signer_keys[0]],
  4876. )
  4877. .unwrap(),
  4878. vec![
  4879. &mut account,
  4880. &mut multisig_account,
  4881. account_info_iter.next().unwrap(),
  4882. ],
  4883. )
  4884. .unwrap();
  4885. }
  4886. #[test]
  4887. fn test_validate_owner() {
  4888. let program_id = crate::id();
  4889. let owner_key = Pubkey::new_unique();
  4890. let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
  4891. for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
  4892. *signer_key = Pubkey::new_unique();
  4893. }
  4894. let mut signer_lamports = 0;
  4895. let mut signer_data = vec![];
  4896. let mut signers = vec![
  4897. AccountInfo::new(
  4898. &owner_key,
  4899. true,
  4900. false,
  4901. &mut signer_lamports,
  4902. &mut signer_data,
  4903. &program_id,
  4904. false,
  4905. Epoch::default(),
  4906. );
  4907. MAX_SIGNERS + 1
  4908. ];
  4909. for (signer, key) in signers.iter_mut().zip(&signer_keys) {
  4910. signer.key = key;
  4911. }
  4912. let mut lamports = 0;
  4913. let mut data = vec![0; Multisig::get_packed_len()];
  4914. let mut multisig = Multisig::unpack_unchecked(&data).unwrap();
  4915. multisig.m = MAX_SIGNERS as u8;
  4916. multisig.n = MAX_SIGNERS as u8;
  4917. multisig.signers = signer_keys;
  4918. multisig.is_initialized = true;
  4919. Multisig::pack(multisig, &mut data).unwrap();
  4920. let owner_account_info = AccountInfo::new(
  4921. &owner_key,
  4922. false,
  4923. false,
  4924. &mut lamports,
  4925. &mut data,
  4926. &program_id,
  4927. false,
  4928. Epoch::default(),
  4929. );
  4930. // full 11 of 11
  4931. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
  4932. // 1 of 11
  4933. {
  4934. let mut multisig =
  4935. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4936. multisig.m = 1;
  4937. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  4938. }
  4939. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
  4940. // 2:1
  4941. {
  4942. let mut multisig =
  4943. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4944. multisig.m = 2;
  4945. multisig.n = 1;
  4946. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  4947. }
  4948. assert_eq!(
  4949. Err(ProgramError::MissingRequiredSignature),
  4950. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
  4951. );
  4952. // 0:11
  4953. {
  4954. let mut multisig =
  4955. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4956. multisig.m = 0;
  4957. multisig.n = 11;
  4958. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  4959. }
  4960. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
  4961. // 2:11 but 0 provided
  4962. {
  4963. let mut multisig =
  4964. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4965. multisig.m = 2;
  4966. multisig.n = 11;
  4967. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  4968. }
  4969. assert_eq!(
  4970. Err(ProgramError::MissingRequiredSignature),
  4971. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &[])
  4972. );
  4973. // 2:11 but 1 provided
  4974. {
  4975. let mut multisig =
  4976. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4977. multisig.m = 2;
  4978. multisig.n = 11;
  4979. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  4980. }
  4981. assert_eq!(
  4982. Err(ProgramError::MissingRequiredSignature),
  4983. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[0..1])
  4984. );
  4985. // 2:11, 2 from middle provided
  4986. {
  4987. let mut multisig =
  4988. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4989. multisig.m = 2;
  4990. multisig.n = 11;
  4991. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  4992. }
  4993. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[5..7])
  4994. .unwrap();
  4995. // 11:11, one is not a signer
  4996. {
  4997. let mut multisig =
  4998. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  4999. multisig.m = 11;
  5000. multisig.n = 11;
  5001. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  5002. }
  5003. signers[5].is_signer = false;
  5004. assert_eq!(
  5005. Err(ProgramError::MissingRequiredSignature),
  5006. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
  5007. );
  5008. signers[5].is_signer = true;
  5009. // 11:11, single signer signs multiple times
  5010. {
  5011. let mut signer_lamports = 0;
  5012. let mut signer_data = vec![];
  5013. let signers = vec![
  5014. AccountInfo::new(
  5015. &signer_keys[5],
  5016. true,
  5017. false,
  5018. &mut signer_lamports,
  5019. &mut signer_data,
  5020. &program_id,
  5021. false,
  5022. Epoch::default(),
  5023. );
  5024. MAX_SIGNERS + 1
  5025. ];
  5026. let mut multisig =
  5027. Multisig::unpack_unchecked(&owner_account_info.data.borrow()).unwrap();
  5028. multisig.m = 11;
  5029. multisig.n = 11;
  5030. Multisig::pack(multisig, &mut owner_account_info.data.borrow_mut()).unwrap();
  5031. assert_eq!(
  5032. Err(ProgramError::MissingRequiredSignature),
  5033. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
  5034. );
  5035. }
  5036. }
  5037. #[test]
  5038. fn test_owner_close_account_dups() {
  5039. let program_id = crate::id();
  5040. let owner_key = Pubkey::new_unique();
  5041. let mint_key = Pubkey::new_unique();
  5042. let mut mint_account =
  5043. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5044. let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
  5045. let rent_key = rent::id();
  5046. let mut rent_sysvar = rent_sysvar();
  5047. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  5048. // create mint
  5049. do_process_instruction_dups(
  5050. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  5051. vec![mint_info.clone(), rent_info.clone()],
  5052. )
  5053. .unwrap();
  5054. let to_close_key = Pubkey::new_unique();
  5055. let mut to_close_account = SolanaAccount::new(
  5056. account_minimum_balance(),
  5057. Account::get_packed_len(),
  5058. &program_id,
  5059. );
  5060. let to_close_account_info: AccountInfo =
  5061. (&to_close_key, true, &mut to_close_account).into();
  5062. let destination_account_key = Pubkey::new_unique();
  5063. let mut destination_account = SolanaAccount::new(
  5064. account_minimum_balance(),
  5065. Account::get_packed_len(),
  5066. &program_id,
  5067. );
  5068. let destination_account_info: AccountInfo =
  5069. (&destination_account_key, true, &mut destination_account).into();
  5070. // create account
  5071. do_process_instruction_dups(
  5072. initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
  5073. vec![
  5074. to_close_account_info.clone(),
  5075. mint_info.clone(),
  5076. to_close_account_info.clone(),
  5077. rent_info.clone(),
  5078. ],
  5079. )
  5080. .unwrap();
  5081. // source-owner close
  5082. do_process_instruction_dups(
  5083. close_account(
  5084. &program_id,
  5085. &to_close_key,
  5086. &destination_account_key,
  5087. &to_close_key,
  5088. &[],
  5089. )
  5090. .unwrap(),
  5091. vec![
  5092. to_close_account_info.clone(),
  5093. destination_account_info.clone(),
  5094. to_close_account_info.clone(),
  5095. ],
  5096. )
  5097. .unwrap();
  5098. assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
  5099. }
  5100. #[test]
  5101. fn test_close_authority_close_account_dups() {
  5102. let program_id = crate::id();
  5103. let owner_key = Pubkey::new_unique();
  5104. let mint_key = Pubkey::new_unique();
  5105. let mut mint_account =
  5106. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5107. let mint_info: AccountInfo = (&mint_key, false, &mut mint_account).into();
  5108. let rent_key = rent::id();
  5109. let mut rent_sysvar = rent_sysvar();
  5110. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  5111. // create mint
  5112. do_process_instruction_dups(
  5113. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  5114. vec![mint_info.clone(), rent_info.clone()],
  5115. )
  5116. .unwrap();
  5117. let to_close_key = Pubkey::new_unique();
  5118. let mut to_close_account = SolanaAccount::new(
  5119. account_minimum_balance(),
  5120. Account::get_packed_len(),
  5121. &program_id,
  5122. );
  5123. let to_close_account_info: AccountInfo =
  5124. (&to_close_key, true, &mut to_close_account).into();
  5125. let destination_account_key = Pubkey::new_unique();
  5126. let mut destination_account = SolanaAccount::new(
  5127. account_minimum_balance(),
  5128. Account::get_packed_len(),
  5129. &program_id,
  5130. );
  5131. let destination_account_info: AccountInfo =
  5132. (&destination_account_key, true, &mut destination_account).into();
  5133. // create account
  5134. do_process_instruction_dups(
  5135. initialize_account(&program_id, &to_close_key, &mint_key, &to_close_key).unwrap(),
  5136. vec![
  5137. to_close_account_info.clone(),
  5138. mint_info.clone(),
  5139. to_close_account_info.clone(),
  5140. rent_info.clone(),
  5141. ],
  5142. )
  5143. .unwrap();
  5144. let mut account = Account::unpack_unchecked(&to_close_account_info.data.borrow()).unwrap();
  5145. account.close_authority = COption::Some(to_close_key);
  5146. account.owner = owner_key;
  5147. Account::pack(account, &mut to_close_account_info.data.borrow_mut()).unwrap();
  5148. do_process_instruction_dups(
  5149. close_account(
  5150. &program_id,
  5151. &to_close_key,
  5152. &destination_account_key,
  5153. &to_close_key,
  5154. &[],
  5155. )
  5156. .unwrap(),
  5157. vec![
  5158. to_close_account_info.clone(),
  5159. destination_account_info.clone(),
  5160. to_close_account_info.clone(),
  5161. ],
  5162. )
  5163. .unwrap();
  5164. assert_eq!(*to_close_account_info.data.borrow(), &[0u8; Account::LEN]);
  5165. }
  5166. #[test]
  5167. fn test_close_account() {
  5168. let program_id = crate::id();
  5169. let mint_key = Pubkey::new_unique();
  5170. let mut mint_account =
  5171. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5172. let account_key = Pubkey::new_unique();
  5173. let mut account_account = SolanaAccount::new(
  5174. account_minimum_balance(),
  5175. Account::get_packed_len(),
  5176. &program_id,
  5177. );
  5178. let account2_key = Pubkey::new_unique();
  5179. let mut account2_account = SolanaAccount::new(
  5180. account_minimum_balance() + 42,
  5181. Account::get_packed_len(),
  5182. &program_id,
  5183. );
  5184. let account3_key = Pubkey::new_unique();
  5185. let mut account3_account = SolanaAccount::new(
  5186. account_minimum_balance(),
  5187. Account::get_packed_len(),
  5188. &program_id,
  5189. );
  5190. let owner_key = Pubkey::new_unique();
  5191. let mut owner_account = SolanaAccount::default();
  5192. let owner2_key = Pubkey::new_unique();
  5193. let mut owner2_account = SolanaAccount::default();
  5194. let mut rent_sysvar = rent_sysvar();
  5195. // uninitialized
  5196. assert_eq!(
  5197. Err(ProgramError::UninitializedAccount),
  5198. do_process_instruction(
  5199. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  5200. vec![
  5201. &mut account_account,
  5202. &mut account3_account,
  5203. &mut owner2_account,
  5204. ],
  5205. )
  5206. );
  5207. // initialize and mint to non-native account
  5208. do_process_instruction(
  5209. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  5210. vec![&mut mint_account, &mut rent_sysvar],
  5211. )
  5212. .unwrap();
  5213. do_process_instruction(
  5214. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  5215. vec![
  5216. &mut account_account,
  5217. &mut mint_account,
  5218. &mut owner_account,
  5219. &mut rent_sysvar,
  5220. ],
  5221. )
  5222. .unwrap();
  5223. do_process_instruction(
  5224. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
  5225. vec![
  5226. &mut mint_account,
  5227. &mut account_account,
  5228. &mut owner_account,
  5229. &mut rent_sysvar,
  5230. ],
  5231. )
  5232. .unwrap();
  5233. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5234. assert_eq!(account.amount, 42);
  5235. // initialize native account
  5236. do_process_instruction(
  5237. initialize_account(
  5238. &program_id,
  5239. &account2_key,
  5240. &crate::native_mint::id(),
  5241. &owner_key,
  5242. )
  5243. .unwrap(),
  5244. vec![
  5245. &mut account2_account,
  5246. &mut mint_account,
  5247. &mut owner_account,
  5248. &mut rent_sysvar,
  5249. ],
  5250. )
  5251. .unwrap();
  5252. let account = Account::unpack_unchecked(&account2_account.data).unwrap();
  5253. assert!(account.is_native());
  5254. assert_eq!(account.amount, 42);
  5255. // close non-native account with balance
  5256. assert_eq!(
  5257. Err(TokenError::NonNativeHasBalance.into()),
  5258. do_process_instruction(
  5259. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  5260. vec![
  5261. &mut account_account,
  5262. &mut account3_account,
  5263. &mut owner_account,
  5264. ],
  5265. )
  5266. );
  5267. assert_eq!(account_account.lamports, account_minimum_balance());
  5268. // empty account
  5269. do_process_instruction(
  5270. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
  5271. vec![&mut account_account, &mut mint_account, &mut owner_account],
  5272. )
  5273. .unwrap();
  5274. // wrong owner
  5275. assert_eq!(
  5276. Err(TokenError::OwnerMismatch.into()),
  5277. do_process_instruction(
  5278. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  5279. vec![
  5280. &mut account_account,
  5281. &mut account3_account,
  5282. &mut owner2_account,
  5283. ],
  5284. )
  5285. );
  5286. // close account
  5287. do_process_instruction(
  5288. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  5289. vec![
  5290. &mut account_account,
  5291. &mut account3_account,
  5292. &mut owner_account,
  5293. ],
  5294. )
  5295. .unwrap();
  5296. assert_eq!(account_account.lamports, 0);
  5297. assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
  5298. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5299. assert_eq!(account.amount, 0);
  5300. // fund and initialize new non-native account to test close authority
  5301. let account_key = Pubkey::new_unique();
  5302. let mut account_account = SolanaAccount::new(
  5303. account_minimum_balance(),
  5304. Account::get_packed_len(),
  5305. &program_id,
  5306. );
  5307. let owner2_key = Pubkey::new_unique();
  5308. let mut owner2_account = SolanaAccount::new(
  5309. account_minimum_balance(),
  5310. Account::get_packed_len(),
  5311. &program_id,
  5312. );
  5313. do_process_instruction(
  5314. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  5315. vec![
  5316. &mut account_account,
  5317. &mut mint_account,
  5318. &mut owner_account,
  5319. &mut rent_sysvar,
  5320. ],
  5321. )
  5322. .unwrap();
  5323. account_account.lamports = 2;
  5324. do_process_instruction(
  5325. set_authority(
  5326. &program_id,
  5327. &account_key,
  5328. Some(&owner2_key),
  5329. AuthorityType::CloseAccount,
  5330. &owner_key,
  5331. &[],
  5332. )
  5333. .unwrap(),
  5334. vec![&mut account_account, &mut owner_account],
  5335. )
  5336. .unwrap();
  5337. // account owner cannot authorize close if close_authority is set
  5338. assert_eq!(
  5339. Err(TokenError::OwnerMismatch.into()),
  5340. do_process_instruction(
  5341. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  5342. vec![
  5343. &mut account_account,
  5344. &mut account3_account,
  5345. &mut owner_account,
  5346. ],
  5347. )
  5348. );
  5349. // close non-native account with close_authority
  5350. do_process_instruction(
  5351. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  5352. vec![
  5353. &mut account_account,
  5354. &mut account3_account,
  5355. &mut owner2_account,
  5356. ],
  5357. )
  5358. .unwrap();
  5359. assert_eq!(account_account.lamports, 0);
  5360. assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2);
  5361. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5362. assert_eq!(account.amount, 0);
  5363. // close native account
  5364. do_process_instruction(
  5365. close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
  5366. vec![
  5367. &mut account2_account,
  5368. &mut account3_account,
  5369. &mut owner_account,
  5370. ],
  5371. )
  5372. .unwrap();
  5373. assert_eq!(account2_account.data, [0u8; Account::LEN]);
  5374. assert_eq!(
  5375. account3_account.lamports,
  5376. 3 * account_minimum_balance() + 2 + 42
  5377. );
  5378. }
  5379. #[test]
  5380. fn test_native_token() {
  5381. let program_id = crate::id();
  5382. let mut mint_account =
  5383. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5384. let account_key = Pubkey::new_unique();
  5385. let mut account_account = SolanaAccount::new(
  5386. account_minimum_balance() + 40,
  5387. Account::get_packed_len(),
  5388. &program_id,
  5389. );
  5390. let account2_key = Pubkey::new_unique();
  5391. let mut account2_account = SolanaAccount::new(
  5392. account_minimum_balance(),
  5393. Account::get_packed_len(),
  5394. &program_id,
  5395. );
  5396. let account3_key = Pubkey::new_unique();
  5397. let mut account3_account = SolanaAccount::new(account_minimum_balance(), 0, &program_id);
  5398. let owner_key = Pubkey::new_unique();
  5399. let mut owner_account = SolanaAccount::default();
  5400. let owner2_key = Pubkey::new_unique();
  5401. let mut owner2_account = SolanaAccount::default();
  5402. let owner3_key = Pubkey::new_unique();
  5403. let mut rent_sysvar = rent_sysvar();
  5404. // initialize native account
  5405. do_process_instruction(
  5406. initialize_account(
  5407. &program_id,
  5408. &account_key,
  5409. &crate::native_mint::id(),
  5410. &owner_key,
  5411. )
  5412. .unwrap(),
  5413. vec![
  5414. &mut account_account,
  5415. &mut mint_account,
  5416. &mut owner_account,
  5417. &mut rent_sysvar,
  5418. ],
  5419. )
  5420. .unwrap();
  5421. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5422. assert!(account.is_native());
  5423. assert_eq!(account.amount, 40);
  5424. // initialize native account
  5425. do_process_instruction(
  5426. initialize_account(
  5427. &program_id,
  5428. &account2_key,
  5429. &crate::native_mint::id(),
  5430. &owner_key,
  5431. )
  5432. .unwrap(),
  5433. vec![
  5434. &mut account2_account,
  5435. &mut mint_account,
  5436. &mut owner_account,
  5437. &mut rent_sysvar,
  5438. ],
  5439. )
  5440. .unwrap();
  5441. let account = Account::unpack_unchecked(&account2_account.data).unwrap();
  5442. assert!(account.is_native());
  5443. assert_eq!(account.amount, 0);
  5444. // mint_to unsupported
  5445. assert_eq!(
  5446. Err(TokenError::NativeNotSupported.into()),
  5447. do_process_instruction(
  5448. mint_to(
  5449. &program_id,
  5450. &crate::native_mint::id(),
  5451. &account_key,
  5452. &owner_key,
  5453. &[],
  5454. 42
  5455. )
  5456. .unwrap(),
  5457. vec![&mut mint_account, &mut account_account, &mut owner_account],
  5458. )
  5459. );
  5460. // burn unsupported
  5461. let bogus_mint_key = Pubkey::new_unique();
  5462. let mut bogus_mint_account =
  5463. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5464. do_process_instruction(
  5465. initialize_mint(&program_id, &bogus_mint_key, &owner_key, None, 2).unwrap(),
  5466. vec![&mut bogus_mint_account, &mut rent_sysvar],
  5467. )
  5468. .unwrap();
  5469. assert_eq!(
  5470. Err(TokenError::NativeNotSupported.into()),
  5471. do_process_instruction(
  5472. burn(
  5473. &program_id,
  5474. &account_key,
  5475. &bogus_mint_key,
  5476. &owner_key,
  5477. &[],
  5478. 42
  5479. )
  5480. .unwrap(),
  5481. vec![
  5482. &mut account_account,
  5483. &mut bogus_mint_account,
  5484. &mut owner_account
  5485. ],
  5486. )
  5487. );
  5488. // ensure can't transfer below rent-exempt reserve
  5489. assert_eq!(
  5490. Err(TokenError::InsufficientFunds.into()),
  5491. do_process_instruction(
  5492. transfer(
  5493. &program_id,
  5494. &account_key,
  5495. &account2_key,
  5496. &owner_key,
  5497. &[],
  5498. 50,
  5499. )
  5500. .unwrap(),
  5501. vec![
  5502. &mut account_account,
  5503. &mut account2_account,
  5504. &mut owner_account,
  5505. ],
  5506. )
  5507. );
  5508. // transfer between native accounts
  5509. do_process_instruction(
  5510. transfer(
  5511. &program_id,
  5512. &account_key,
  5513. &account2_key,
  5514. &owner_key,
  5515. &[],
  5516. 40,
  5517. )
  5518. .unwrap(),
  5519. vec![
  5520. &mut account_account,
  5521. &mut account2_account,
  5522. &mut owner_account,
  5523. ],
  5524. )
  5525. .unwrap();
  5526. assert_eq!(account_account.lamports, account_minimum_balance());
  5527. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5528. assert!(account.is_native());
  5529. assert_eq!(account.amount, 0);
  5530. assert_eq!(account2_account.lamports, account_minimum_balance() + 40);
  5531. let account = Account::unpack_unchecked(&account2_account.data).unwrap();
  5532. assert!(account.is_native());
  5533. assert_eq!(account.amount, 40);
  5534. // set close authority
  5535. do_process_instruction(
  5536. set_authority(
  5537. &program_id,
  5538. &account_key,
  5539. Some(&owner3_key),
  5540. AuthorityType::CloseAccount,
  5541. &owner_key,
  5542. &[],
  5543. )
  5544. .unwrap(),
  5545. vec![&mut account_account, &mut owner_account],
  5546. )
  5547. .unwrap();
  5548. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5549. assert_eq!(account.close_authority, COption::Some(owner3_key));
  5550. // set new account owner
  5551. do_process_instruction(
  5552. set_authority(
  5553. &program_id,
  5554. &account_key,
  5555. Some(&owner2_key),
  5556. AuthorityType::AccountOwner,
  5557. &owner_key,
  5558. &[],
  5559. )
  5560. .unwrap(),
  5561. vec![&mut account_account, &mut owner_account],
  5562. )
  5563. .unwrap();
  5564. // close authority cleared
  5565. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5566. assert_eq!(account.close_authority, COption::None);
  5567. // close native account
  5568. do_process_instruction(
  5569. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  5570. vec![
  5571. &mut account_account,
  5572. &mut account3_account,
  5573. &mut owner2_account,
  5574. ],
  5575. )
  5576. .unwrap();
  5577. assert_eq!(account_account.lamports, 0);
  5578. assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
  5579. assert_eq!(account_account.data, [0u8; Account::LEN]);
  5580. }
  5581. #[test]
  5582. fn test_overflow() {
  5583. let program_id = crate::id();
  5584. let account_key = Pubkey::new_unique();
  5585. let mut account_account = SolanaAccount::new(
  5586. account_minimum_balance(),
  5587. Account::get_packed_len(),
  5588. &program_id,
  5589. );
  5590. let account2_key = Pubkey::new_unique();
  5591. let mut account2_account = SolanaAccount::new(
  5592. account_minimum_balance(),
  5593. Account::get_packed_len(),
  5594. &program_id,
  5595. );
  5596. let owner_key = Pubkey::new_unique();
  5597. let mut owner_account = SolanaAccount::default();
  5598. let owner2_key = Pubkey::new_unique();
  5599. let mut owner2_account = SolanaAccount::default();
  5600. let mint_owner_key = Pubkey::new_unique();
  5601. let mut mint_owner_account = SolanaAccount::default();
  5602. let mint_key = Pubkey::new_unique();
  5603. let mut mint_account =
  5604. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5605. let mut rent_sysvar = rent_sysvar();
  5606. // create new mint with owner
  5607. do_process_instruction(
  5608. initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
  5609. vec![&mut mint_account, &mut rent_sysvar],
  5610. )
  5611. .unwrap();
  5612. // create an account
  5613. do_process_instruction(
  5614. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  5615. vec![
  5616. &mut account_account,
  5617. &mut mint_account,
  5618. &mut owner_account,
  5619. &mut rent_sysvar,
  5620. ],
  5621. )
  5622. .unwrap();
  5623. // create another account
  5624. do_process_instruction(
  5625. initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
  5626. vec![
  5627. &mut account2_account,
  5628. &mut mint_account,
  5629. &mut owner2_account,
  5630. &mut rent_sysvar,
  5631. ],
  5632. )
  5633. .unwrap();
  5634. // mint the max to an account
  5635. do_process_instruction(
  5636. mint_to(
  5637. &program_id,
  5638. &mint_key,
  5639. &account_key,
  5640. &mint_owner_key,
  5641. &[],
  5642. u64::MAX,
  5643. )
  5644. .unwrap(),
  5645. vec![
  5646. &mut mint_account,
  5647. &mut account_account,
  5648. &mut mint_owner_account,
  5649. ],
  5650. )
  5651. .unwrap();
  5652. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5653. assert_eq!(account.amount, u64::MAX);
  5654. // attempt to mint one more to account
  5655. assert_eq!(
  5656. Err(TokenError::Overflow.into()),
  5657. do_process_instruction(
  5658. mint_to(
  5659. &program_id,
  5660. &mint_key,
  5661. &account_key,
  5662. &mint_owner_key,
  5663. &[],
  5664. 1,
  5665. )
  5666. .unwrap(),
  5667. vec![
  5668. &mut mint_account,
  5669. &mut account_account,
  5670. &mut mint_owner_account,
  5671. ],
  5672. )
  5673. );
  5674. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5675. assert_eq!(account.amount, u64::MAX);
  5676. // attempt to mint one more to the other account
  5677. assert_eq!(
  5678. Err(TokenError::Overflow.into()),
  5679. do_process_instruction(
  5680. mint_to(
  5681. &program_id,
  5682. &mint_key,
  5683. &account2_key,
  5684. &mint_owner_key,
  5685. &[],
  5686. 1,
  5687. )
  5688. .unwrap(),
  5689. vec![
  5690. &mut mint_account,
  5691. &mut account2_account,
  5692. &mut mint_owner_account,
  5693. ],
  5694. )
  5695. );
  5696. // burn some of the supply
  5697. do_process_instruction(
  5698. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
  5699. vec![&mut account_account, &mut mint_account, &mut owner_account],
  5700. )
  5701. .unwrap();
  5702. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5703. assert_eq!(account.amount, u64::MAX - 100);
  5704. do_process_instruction(
  5705. mint_to(
  5706. &program_id,
  5707. &mint_key,
  5708. &account_key,
  5709. &mint_owner_key,
  5710. &[],
  5711. 100,
  5712. )
  5713. .unwrap(),
  5714. vec![
  5715. &mut mint_account,
  5716. &mut account_account,
  5717. &mut mint_owner_account,
  5718. ],
  5719. )
  5720. .unwrap();
  5721. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  5722. assert_eq!(account.amount, u64::MAX);
  5723. // manipulate account balance to attempt overflow transfer
  5724. let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
  5725. account.amount = 1;
  5726. Account::pack(account, &mut account2_account.data).unwrap();
  5727. assert_eq!(
  5728. Err(TokenError::Overflow.into()),
  5729. do_process_instruction(
  5730. transfer(
  5731. &program_id,
  5732. &account2_key,
  5733. &account_key,
  5734. &owner2_key,
  5735. &[],
  5736. 1,
  5737. )
  5738. .unwrap(),
  5739. vec![
  5740. &mut account2_account,
  5741. &mut account_account,
  5742. &mut owner2_account,
  5743. ],
  5744. )
  5745. );
  5746. }
  5747. #[test]
  5748. fn test_frozen() {
  5749. let program_id = crate::id();
  5750. let account_key = Pubkey::new_unique();
  5751. let mut account_account = SolanaAccount::new(
  5752. account_minimum_balance(),
  5753. Account::get_packed_len(),
  5754. &program_id,
  5755. );
  5756. let account2_key = Pubkey::new_unique();
  5757. let mut account2_account = SolanaAccount::new(
  5758. account_minimum_balance(),
  5759. Account::get_packed_len(),
  5760. &program_id,
  5761. );
  5762. let owner_key = Pubkey::new_unique();
  5763. let mut owner_account = SolanaAccount::default();
  5764. let mint_key = Pubkey::new_unique();
  5765. let mut mint_account =
  5766. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5767. let mut rent_sysvar = rent_sysvar();
  5768. // create new mint and fund first account
  5769. do_process_instruction(
  5770. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  5771. vec![&mut mint_account, &mut rent_sysvar],
  5772. )
  5773. .unwrap();
  5774. // create account
  5775. do_process_instruction(
  5776. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  5777. vec![
  5778. &mut account_account,
  5779. &mut mint_account,
  5780. &mut owner_account,
  5781. &mut rent_sysvar,
  5782. ],
  5783. )
  5784. .unwrap();
  5785. // create another account
  5786. do_process_instruction(
  5787. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  5788. vec![
  5789. &mut account2_account,
  5790. &mut mint_account,
  5791. &mut owner_account,
  5792. &mut rent_sysvar,
  5793. ],
  5794. )
  5795. .unwrap();
  5796. // fund first account
  5797. do_process_instruction(
  5798. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  5799. vec![&mut mint_account, &mut account_account, &mut owner_account],
  5800. )
  5801. .unwrap();
  5802. // no transfer if either account is frozen
  5803. let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
  5804. account.state = AccountState::Frozen;
  5805. Account::pack(account, &mut account2_account.data).unwrap();
  5806. assert_eq!(
  5807. Err(TokenError::AccountFrozen.into()),
  5808. do_process_instruction(
  5809. transfer(
  5810. &program_id,
  5811. &account_key,
  5812. &account2_key,
  5813. &owner_key,
  5814. &[],
  5815. 500,
  5816. )
  5817. .unwrap(),
  5818. vec![
  5819. &mut account_account,
  5820. &mut account2_account,
  5821. &mut owner_account,
  5822. ],
  5823. )
  5824. );
  5825. let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
  5826. account.state = AccountState::Initialized;
  5827. Account::pack(account, &mut account_account.data).unwrap();
  5828. let mut account = Account::unpack_unchecked(&account2_account.data).unwrap();
  5829. account.state = AccountState::Frozen;
  5830. Account::pack(account, &mut account2_account.data).unwrap();
  5831. assert_eq!(
  5832. Err(TokenError::AccountFrozen.into()),
  5833. do_process_instruction(
  5834. transfer(
  5835. &program_id,
  5836. &account_key,
  5837. &account2_key,
  5838. &owner_key,
  5839. &[],
  5840. 500,
  5841. )
  5842. .unwrap(),
  5843. vec![
  5844. &mut account_account,
  5845. &mut account2_account,
  5846. &mut owner_account,
  5847. ],
  5848. )
  5849. );
  5850. // no approve if account is frozen
  5851. let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
  5852. account.state = AccountState::Frozen;
  5853. Account::pack(account, &mut account_account.data).unwrap();
  5854. let delegate_key = Pubkey::new_unique();
  5855. let mut delegate_account = SolanaAccount::default();
  5856. assert_eq!(
  5857. Err(TokenError::AccountFrozen.into()),
  5858. do_process_instruction(
  5859. approve(
  5860. &program_id,
  5861. &account_key,
  5862. &delegate_key,
  5863. &owner_key,
  5864. &[],
  5865. 100
  5866. )
  5867. .unwrap(),
  5868. vec![
  5869. &mut account_account,
  5870. &mut delegate_account,
  5871. &mut owner_account,
  5872. ],
  5873. )
  5874. );
  5875. // no revoke if account is frozen
  5876. let mut account = Account::unpack_unchecked(&account_account.data).unwrap();
  5877. account.delegate = COption::Some(delegate_key);
  5878. account.delegated_amount = 100;
  5879. Account::pack(account, &mut account_account.data).unwrap();
  5880. assert_eq!(
  5881. Err(TokenError::AccountFrozen.into()),
  5882. do_process_instruction(
  5883. revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
  5884. vec![&mut account_account, &mut owner_account],
  5885. )
  5886. );
  5887. // no set authority if account is frozen
  5888. let new_owner_key = Pubkey::new_unique();
  5889. assert_eq!(
  5890. Err(TokenError::AccountFrozen.into()),
  5891. do_process_instruction(
  5892. set_authority(
  5893. &program_id,
  5894. &account_key,
  5895. Some(&new_owner_key),
  5896. AuthorityType::AccountOwner,
  5897. &owner_key,
  5898. &[]
  5899. )
  5900. .unwrap(),
  5901. vec![&mut account_account, &mut owner_account,],
  5902. )
  5903. );
  5904. // no mint_to if destination account is frozen
  5905. assert_eq!(
  5906. Err(TokenError::AccountFrozen.into()),
  5907. do_process_instruction(
  5908. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 100).unwrap(),
  5909. vec![&mut mint_account, &mut account_account, &mut owner_account,],
  5910. )
  5911. );
  5912. // no burn if account is frozen
  5913. assert_eq!(
  5914. Err(TokenError::AccountFrozen.into()),
  5915. do_process_instruction(
  5916. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
  5917. vec![&mut account_account, &mut mint_account, &mut owner_account],
  5918. )
  5919. );
  5920. }
  5921. #[test]
  5922. fn test_freeze_thaw_dups() {
  5923. let program_id = crate::id();
  5924. let account1_key = Pubkey::new_unique();
  5925. let mut account1_account = SolanaAccount::new(
  5926. account_minimum_balance(),
  5927. Account::get_packed_len(),
  5928. &program_id,
  5929. );
  5930. let account1_info: AccountInfo = (&account1_key, true, &mut account1_account).into();
  5931. let owner_key = Pubkey::new_unique();
  5932. let mint_key = Pubkey::new_unique();
  5933. let mut mint_account =
  5934. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5935. let mint_info: AccountInfo = (&mint_key, true, &mut mint_account).into();
  5936. let rent_key = rent::id();
  5937. let mut rent_sysvar = rent_sysvar();
  5938. let rent_info: AccountInfo = (&rent_key, false, &mut rent_sysvar).into();
  5939. // create mint
  5940. do_process_instruction_dups(
  5941. initialize_mint(&program_id, &mint_key, &owner_key, Some(&account1_key), 2).unwrap(),
  5942. vec![mint_info.clone(), rent_info.clone()],
  5943. )
  5944. .unwrap();
  5945. // create account
  5946. do_process_instruction_dups(
  5947. initialize_account(&program_id, &account1_key, &mint_key, &account1_key).unwrap(),
  5948. vec![
  5949. account1_info.clone(),
  5950. mint_info.clone(),
  5951. account1_info.clone(),
  5952. rent_info.clone(),
  5953. ],
  5954. )
  5955. .unwrap();
  5956. // freeze where mint freeze_authority is account
  5957. do_process_instruction_dups(
  5958. freeze_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
  5959. vec![
  5960. account1_info.clone(),
  5961. mint_info.clone(),
  5962. account1_info.clone(),
  5963. ],
  5964. )
  5965. .unwrap();
  5966. // thaw where mint freeze_authority is account
  5967. let mut account = Account::unpack_unchecked(&account1_info.data.borrow()).unwrap();
  5968. account.state = AccountState::Frozen;
  5969. Account::pack(account, &mut account1_info.data.borrow_mut()).unwrap();
  5970. do_process_instruction_dups(
  5971. thaw_account(&program_id, &account1_key, &mint_key, &account1_key, &[]).unwrap(),
  5972. vec![
  5973. account1_info.clone(),
  5974. mint_info.clone(),
  5975. account1_info.clone(),
  5976. ],
  5977. )
  5978. .unwrap();
  5979. }
  5980. #[test]
  5981. fn test_freeze_account() {
  5982. let program_id = crate::id();
  5983. let account_key = Pubkey::new_unique();
  5984. let mut account_account = SolanaAccount::new(
  5985. account_minimum_balance(),
  5986. Account::get_packed_len(),
  5987. &program_id,
  5988. );
  5989. let account_owner_key = Pubkey::new_unique();
  5990. let mut account_owner_account = SolanaAccount::default();
  5991. let owner_key = Pubkey::new_unique();
  5992. let mut owner_account = SolanaAccount::default();
  5993. let owner2_key = Pubkey::new_unique();
  5994. let mut owner2_account = SolanaAccount::default();
  5995. let mint_key = Pubkey::new_unique();
  5996. let mut mint_account =
  5997. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  5998. let mut rent_sysvar = rent_sysvar();
  5999. // create new mint with owner different from account owner
  6000. do_process_instruction(
  6001. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6002. vec![&mut mint_account, &mut rent_sysvar],
  6003. )
  6004. .unwrap();
  6005. // create account
  6006. do_process_instruction(
  6007. initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
  6008. vec![
  6009. &mut account_account,
  6010. &mut mint_account,
  6011. &mut account_owner_account,
  6012. &mut rent_sysvar,
  6013. ],
  6014. )
  6015. .unwrap();
  6016. // mint to account
  6017. do_process_instruction(
  6018. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  6019. vec![&mut mint_account, &mut account_account, &mut owner_account],
  6020. )
  6021. .unwrap();
  6022. // mint cannot freeze
  6023. assert_eq!(
  6024. Err(TokenError::MintCannotFreeze.into()),
  6025. do_process_instruction(
  6026. freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  6027. vec![&mut account_account, &mut mint_account, &mut owner_account],
  6028. )
  6029. );
  6030. // missing freeze_authority
  6031. let mut mint = Mint::unpack_unchecked(&mint_account.data).unwrap();
  6032. mint.freeze_authority = COption::Some(owner_key);
  6033. Mint::pack(mint, &mut mint_account.data).unwrap();
  6034. assert_eq!(
  6035. Err(TokenError::OwnerMismatch.into()),
  6036. do_process_instruction(
  6037. freeze_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
  6038. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  6039. )
  6040. );
  6041. // check explicit thaw
  6042. assert_eq!(
  6043. Err(TokenError::InvalidState.into()),
  6044. do_process_instruction(
  6045. thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
  6046. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  6047. )
  6048. );
  6049. // freeze
  6050. do_process_instruction(
  6051. freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  6052. vec![&mut account_account, &mut mint_account, &mut owner_account],
  6053. )
  6054. .unwrap();
  6055. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  6056. assert_eq!(account.state, AccountState::Frozen);
  6057. // check explicit freeze
  6058. assert_eq!(
  6059. Err(TokenError::InvalidState.into()),
  6060. do_process_instruction(
  6061. freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  6062. vec![&mut account_account, &mut mint_account, &mut owner_account],
  6063. )
  6064. );
  6065. // check thaw authority
  6066. assert_eq!(
  6067. Err(TokenError::OwnerMismatch.into()),
  6068. do_process_instruction(
  6069. thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
  6070. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  6071. )
  6072. );
  6073. // thaw
  6074. do_process_instruction(
  6075. thaw_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  6076. vec![&mut account_account, &mut mint_account, &mut owner_account],
  6077. )
  6078. .unwrap();
  6079. let account = Account::unpack_unchecked(&account_account.data).unwrap();
  6080. assert_eq!(account.state, AccountState::Initialized);
  6081. }
  6082. #[test]
  6083. fn test_initialize_account2_and_3() {
  6084. let program_id = crate::id();
  6085. let account_key = Pubkey::new_unique();
  6086. let mut account_account = SolanaAccount::new(
  6087. account_minimum_balance(),
  6088. Account::get_packed_len(),
  6089. &program_id,
  6090. );
  6091. let mut account2_account = SolanaAccount::new(
  6092. account_minimum_balance(),
  6093. Account::get_packed_len(),
  6094. &program_id,
  6095. );
  6096. let mut account3_account = SolanaAccount::new(
  6097. account_minimum_balance(),
  6098. Account::get_packed_len(),
  6099. &program_id,
  6100. );
  6101. let owner_key = Pubkey::new_unique();
  6102. let mut owner_account = SolanaAccount::default();
  6103. let mint_key = Pubkey::new_unique();
  6104. let mut mint_account =
  6105. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  6106. let mut rent_sysvar = rent_sysvar();
  6107. // create mint
  6108. do_process_instruction(
  6109. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6110. vec![&mut mint_account, &mut rent_sysvar],
  6111. )
  6112. .unwrap();
  6113. do_process_instruction(
  6114. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  6115. vec![
  6116. &mut account_account,
  6117. &mut mint_account,
  6118. &mut owner_account,
  6119. &mut rent_sysvar,
  6120. ],
  6121. )
  6122. .unwrap();
  6123. do_process_instruction(
  6124. initialize_account2(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  6125. vec![&mut account2_account, &mut mint_account, &mut rent_sysvar],
  6126. )
  6127. .unwrap();
  6128. assert_eq!(account_account, account2_account);
  6129. do_process_instruction(
  6130. initialize_account3(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  6131. vec![&mut account3_account, &mut mint_account],
  6132. )
  6133. .unwrap();
  6134. assert_eq!(account_account, account3_account);
  6135. }
  6136. #[test]
  6137. fn test_sync_native() {
  6138. let program_id = crate::id();
  6139. let mint_key = Pubkey::new_unique();
  6140. let mut mint_account =
  6141. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  6142. let native_account_key = Pubkey::new_unique();
  6143. let lamports = 40;
  6144. let mut native_account = SolanaAccount::new(
  6145. account_minimum_balance() + lamports,
  6146. Account::get_packed_len(),
  6147. &program_id,
  6148. );
  6149. let non_native_account_key = Pubkey::new_unique();
  6150. let mut non_native_account = SolanaAccount::new(
  6151. account_minimum_balance() + 50,
  6152. Account::get_packed_len(),
  6153. &program_id,
  6154. );
  6155. let owner_key = Pubkey::new_unique();
  6156. let mut owner_account = SolanaAccount::default();
  6157. let mut rent_sysvar = rent_sysvar();
  6158. // initialize non-native mint
  6159. do_process_instruction(
  6160. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6161. vec![&mut mint_account, &mut rent_sysvar],
  6162. )
  6163. .unwrap();
  6164. // initialize non-native account
  6165. do_process_instruction(
  6166. initialize_account(&program_id, &non_native_account_key, &mint_key, &owner_key)
  6167. .unwrap(),
  6168. vec![
  6169. &mut non_native_account,
  6170. &mut mint_account,
  6171. &mut owner_account,
  6172. &mut rent_sysvar,
  6173. ],
  6174. )
  6175. .unwrap();
  6176. let account = Account::unpack_unchecked(&non_native_account.data).unwrap();
  6177. assert!(!account.is_native());
  6178. assert_eq!(account.amount, 0);
  6179. // fail sync non-native
  6180. assert_eq!(
  6181. Err(TokenError::NonNativeNotSupported.into()),
  6182. do_process_instruction(
  6183. sync_native(&program_id, &non_native_account_key,).unwrap(),
  6184. vec![&mut non_native_account],
  6185. )
  6186. );
  6187. // fail sync uninitialized
  6188. assert_eq!(
  6189. Err(ProgramError::UninitializedAccount),
  6190. do_process_instruction(
  6191. sync_native(&program_id, &native_account_key,).unwrap(),
  6192. vec![&mut native_account],
  6193. )
  6194. );
  6195. // wrap native account
  6196. do_process_instruction(
  6197. initialize_account(
  6198. &program_id,
  6199. &native_account_key,
  6200. &crate::native_mint::id(),
  6201. &owner_key,
  6202. )
  6203. .unwrap(),
  6204. vec![
  6205. &mut native_account,
  6206. &mut mint_account,
  6207. &mut owner_account,
  6208. &mut rent_sysvar,
  6209. ],
  6210. )
  6211. .unwrap();
  6212. // fail sync, not owned by program
  6213. let not_program_id = Pubkey::new_unique();
  6214. native_account.owner = not_program_id;
  6215. assert_eq!(
  6216. Err(ProgramError::IncorrectProgramId),
  6217. do_process_instruction(
  6218. sync_native(&program_id, &native_account_key,).unwrap(),
  6219. vec![&mut native_account],
  6220. )
  6221. );
  6222. native_account.owner = program_id;
  6223. let account = Account::unpack_unchecked(&native_account.data).unwrap();
  6224. assert!(account.is_native());
  6225. assert_eq!(account.amount, lamports);
  6226. // sync, no change
  6227. do_process_instruction(
  6228. sync_native(&program_id, &native_account_key).unwrap(),
  6229. vec![&mut native_account],
  6230. )
  6231. .unwrap();
  6232. let account = Account::unpack_unchecked(&native_account.data).unwrap();
  6233. assert_eq!(account.amount, lamports);
  6234. // transfer sol
  6235. let new_lamports = lamports + 50;
  6236. native_account.lamports = account_minimum_balance() + new_lamports;
  6237. // success sync
  6238. do_process_instruction(
  6239. sync_native(&program_id, &native_account_key).unwrap(),
  6240. vec![&mut native_account],
  6241. )
  6242. .unwrap();
  6243. let account = Account::unpack_unchecked(&native_account.data).unwrap();
  6244. assert_eq!(account.amount, new_lamports);
  6245. // reduce sol
  6246. native_account.lamports -= 1;
  6247. // fail sync
  6248. assert_eq!(
  6249. Err(TokenError::InvalidState.into()),
  6250. do_process_instruction(
  6251. sync_native(&program_id, &native_account_key,).unwrap(),
  6252. vec![&mut native_account],
  6253. )
  6254. );
  6255. }
  6256. #[test]
  6257. #[serial]
  6258. fn test_get_account_data_size() {
  6259. // see integration tests for return-data validity
  6260. let program_id = crate::id();
  6261. let owner_key = Pubkey::new_unique();
  6262. let mut rent_sysvar = rent_sysvar();
  6263. let mut mint_account =
  6264. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  6265. let mint_key = Pubkey::new_unique();
  6266. // fail if an invalid mint is passed in
  6267. assert_eq!(
  6268. Err(TokenError::InvalidMint.into()),
  6269. do_process_instruction(
  6270. get_account_data_size(&program_id, &mint_key).unwrap(),
  6271. vec![&mut mint_account],
  6272. )
  6273. );
  6274. do_process_instruction(
  6275. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6276. vec![&mut mint_account, &mut rent_sysvar],
  6277. )
  6278. .unwrap();
  6279. set_expected_data(Account::LEN.to_le_bytes().to_vec());
  6280. do_process_instruction(
  6281. get_account_data_size(&program_id, &mint_key).unwrap(),
  6282. vec![&mut mint_account],
  6283. )
  6284. .unwrap();
  6285. }
  6286. #[test]
  6287. fn test_initialize_immutable_owner() {
  6288. let program_id = crate::id();
  6289. let account_key = Pubkey::new_unique();
  6290. let mut account_account = SolanaAccount::new(
  6291. account_minimum_balance(),
  6292. Account::get_packed_len(),
  6293. &program_id,
  6294. );
  6295. let owner_key = Pubkey::new_unique();
  6296. let mut owner_account = SolanaAccount::default();
  6297. let mint_key = Pubkey::new_unique();
  6298. let mut mint_account =
  6299. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  6300. let mut rent_sysvar = rent_sysvar();
  6301. // create mint
  6302. do_process_instruction(
  6303. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6304. vec![&mut mint_account, &mut rent_sysvar],
  6305. )
  6306. .unwrap();
  6307. // success initialize immutable
  6308. do_process_instruction(
  6309. initialize_immutable_owner(&program_id, &account_key).unwrap(),
  6310. vec![&mut account_account],
  6311. )
  6312. .unwrap();
  6313. // create account
  6314. do_process_instruction(
  6315. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  6316. vec![
  6317. &mut account_account,
  6318. &mut mint_account,
  6319. &mut owner_account,
  6320. &mut rent_sysvar,
  6321. ],
  6322. )
  6323. .unwrap();
  6324. // fail post-init
  6325. assert_eq!(
  6326. Err(TokenError::AlreadyInUse.into()),
  6327. do_process_instruction(
  6328. initialize_immutable_owner(&program_id, &account_key).unwrap(),
  6329. vec![&mut account_account],
  6330. )
  6331. );
  6332. }
  6333. #[test]
  6334. #[serial]
  6335. fn test_amount_to_ui_amount() {
  6336. let program_id = crate::id();
  6337. let owner_key = Pubkey::new_unique();
  6338. let mint_key = Pubkey::new_unique();
  6339. let mut mint_account =
  6340. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  6341. let mut rent_sysvar = rent_sysvar();
  6342. // fail if an invalid mint is passed in
  6343. assert_eq!(
  6344. Err(TokenError::InvalidMint.into()),
  6345. do_process_instruction(
  6346. amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
  6347. vec![&mut mint_account],
  6348. )
  6349. );
  6350. // create mint
  6351. do_process_instruction(
  6352. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6353. vec![&mut mint_account, &mut rent_sysvar],
  6354. )
  6355. .unwrap();
  6356. set_expected_data("0.23".as_bytes().to_vec());
  6357. do_process_instruction(
  6358. amount_to_ui_amount(&program_id, &mint_key, 23).unwrap(),
  6359. vec![&mut mint_account],
  6360. )
  6361. .unwrap();
  6362. set_expected_data("1.1".as_bytes().to_vec());
  6363. do_process_instruction(
  6364. amount_to_ui_amount(&program_id, &mint_key, 110).unwrap(),
  6365. vec![&mut mint_account],
  6366. )
  6367. .unwrap();
  6368. set_expected_data("42".as_bytes().to_vec());
  6369. do_process_instruction(
  6370. amount_to_ui_amount(&program_id, &mint_key, 4200).unwrap(),
  6371. vec![&mut mint_account],
  6372. )
  6373. .unwrap();
  6374. set_expected_data("0".as_bytes().to_vec());
  6375. do_process_instruction(
  6376. amount_to_ui_amount(&program_id, &mint_key, 0).unwrap(),
  6377. vec![&mut mint_account],
  6378. )
  6379. .unwrap();
  6380. }
  6381. #[test]
  6382. #[serial]
  6383. fn test_ui_amount_to_amount() {
  6384. let program_id = crate::id();
  6385. let owner_key = Pubkey::new_unique();
  6386. let mint_key = Pubkey::new_unique();
  6387. let mut mint_account =
  6388. SolanaAccount::new(mint_minimum_balance(), Mint::get_packed_len(), &program_id);
  6389. let mut rent_sysvar = rent_sysvar();
  6390. // fail if an invalid mint is passed in
  6391. assert_eq!(
  6392. Err(TokenError::InvalidMint.into()),
  6393. do_process_instruction(
  6394. ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
  6395. vec![&mut mint_account],
  6396. )
  6397. );
  6398. // create mint
  6399. do_process_instruction(
  6400. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  6401. vec![&mut mint_account, &mut rent_sysvar],
  6402. )
  6403. .unwrap();
  6404. set_expected_data(23u64.to_le_bytes().to_vec());
  6405. do_process_instruction(
  6406. ui_amount_to_amount(&program_id, &mint_key, "0.23").unwrap(),
  6407. vec![&mut mint_account],
  6408. )
  6409. .unwrap();
  6410. set_expected_data(20u64.to_le_bytes().to_vec());
  6411. do_process_instruction(
  6412. ui_amount_to_amount(&program_id, &mint_key, "0.20").unwrap(),
  6413. vec![&mut mint_account],
  6414. )
  6415. .unwrap();
  6416. set_expected_data(20u64.to_le_bytes().to_vec());
  6417. do_process_instruction(
  6418. ui_amount_to_amount(&program_id, &mint_key, "0.2000").unwrap(),
  6419. vec![&mut mint_account],
  6420. )
  6421. .unwrap();
  6422. set_expected_data(20u64.to_le_bytes().to_vec());
  6423. do_process_instruction(
  6424. ui_amount_to_amount(&program_id, &mint_key, ".20").unwrap(),
  6425. vec![&mut mint_account],
  6426. )
  6427. .unwrap();
  6428. set_expected_data(110u64.to_le_bytes().to_vec());
  6429. do_process_instruction(
  6430. ui_amount_to_amount(&program_id, &mint_key, "1.1").unwrap(),
  6431. vec![&mut mint_account],
  6432. )
  6433. .unwrap();
  6434. set_expected_data(110u64.to_le_bytes().to_vec());
  6435. do_process_instruction(
  6436. ui_amount_to_amount(&program_id, &mint_key, "1.10").unwrap(),
  6437. vec![&mut mint_account],
  6438. )
  6439. .unwrap();
  6440. set_expected_data(4200u64.to_le_bytes().to_vec());
  6441. do_process_instruction(
  6442. ui_amount_to_amount(&program_id, &mint_key, "42").unwrap(),
  6443. vec![&mut mint_account],
  6444. )
  6445. .unwrap();
  6446. set_expected_data(4200u64.to_le_bytes().to_vec());
  6447. do_process_instruction(
  6448. ui_amount_to_amount(&program_id, &mint_key, "42.").unwrap(),
  6449. vec![&mut mint_account],
  6450. )
  6451. .unwrap();
  6452. set_expected_data(0u64.to_le_bytes().to_vec());
  6453. do_process_instruction(
  6454. ui_amount_to_amount(&program_id, &mint_key, "0").unwrap(),
  6455. vec![&mut mint_account],
  6456. )
  6457. .unwrap();
  6458. // fail if invalid ui_amount passed in
  6459. assert_eq!(
  6460. Err(ProgramError::InvalidArgument),
  6461. do_process_instruction(
  6462. ui_amount_to_amount(&program_id, &mint_key, "").unwrap(),
  6463. vec![&mut mint_account],
  6464. )
  6465. );
  6466. assert_eq!(
  6467. Err(ProgramError::InvalidArgument),
  6468. do_process_instruction(
  6469. ui_amount_to_amount(&program_id, &mint_key, ".").unwrap(),
  6470. vec![&mut mint_account],
  6471. )
  6472. );
  6473. assert_eq!(
  6474. Err(ProgramError::InvalidArgument),
  6475. do_process_instruction(
  6476. ui_amount_to_amount(&program_id, &mint_key, "0.111").unwrap(),
  6477. vec![&mut mint_account],
  6478. )
  6479. );
  6480. assert_eq!(
  6481. Err(ProgramError::InvalidArgument),
  6482. do_process_instruction(
  6483. ui_amount_to_amount(&program_id, &mint_key, "0.t").unwrap(),
  6484. vec![&mut mint_account],
  6485. )
  6486. );
  6487. }
  6488. }