processor.rs 183 KB

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