processor.rs 129 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851
  1. //! Program state processor
  2. #![cfg(feature = "program")]
  3. use crate::{
  4. error::TokenError,
  5. instruction::{is_valid_signer_index, AuthorityType, TokenInstruction},
  6. option::COption,
  7. state::{self, Account, AccountState, IsInitialized, Mint, Multisig},
  8. };
  9. use num_traits::FromPrimitive;
  10. use solana_sdk::{
  11. account_info::{next_account_info, AccountInfo},
  12. decode_error::DecodeError,
  13. entrypoint::ProgramResult,
  14. info,
  15. program_error::{PrintProgramError, ProgramError},
  16. pubkey::Pubkey,
  17. sysvar::{rent::Rent, Sysvar},
  18. };
  19. use std::mem::size_of;
  20. /// Program state handler.
  21. pub struct Processor {}
  22. impl Processor {
  23. /// Processes an [InitializeMint](enum.TokenInstruction.html) instruction.
  24. pub fn process_initialize_mint(
  25. accounts: &[AccountInfo],
  26. decimals: u8,
  27. mint_authority: Pubkey,
  28. freeze_authority: COption<Pubkey>,
  29. ) -> ProgramResult {
  30. let account_info_iter = &mut accounts.iter();
  31. let mint_info = next_account_info(account_info_iter)?;
  32. let mint_info_data_len = mint_info.data_len();
  33. let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
  34. let mut mint_info_data = mint_info.data.borrow_mut();
  35. let mut mint: &mut Mint = state::unpack_unchecked(&mut mint_info_data)?;
  36. if mint.is_initialized {
  37. return Err(TokenError::AlreadyInUse.into());
  38. }
  39. if !rent.is_exempt(mint_info.lamports(), mint_info_data_len) {
  40. return Err(TokenError::NotRentExempt.into());
  41. }
  42. mint.mint_authority = COption::Some(mint_authority);
  43. mint.decimals = decimals;
  44. mint.is_initialized = true;
  45. mint.freeze_authority = freeze_authority;
  46. Ok(())
  47. }
  48. /// Processes an [InitializeAccount](enum.TokenInstruction.html) instruction.
  49. pub fn process_initialize_account(accounts: &[AccountInfo]) -> ProgramResult {
  50. let account_info_iter = &mut accounts.iter();
  51. let new_account_info = next_account_info(account_info_iter)?;
  52. let mint_info = next_account_info(account_info_iter)?;
  53. let owner_info = next_account_info(account_info_iter)?;
  54. let new_account_info_data_len = new_account_info.data_len();
  55. let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
  56. let mut new_account_data = new_account_info.data.borrow_mut();
  57. let mut account: &mut Account = state::unpack_unchecked(&mut new_account_data)?;
  58. if account.is_initialized() {
  59. return Err(TokenError::AlreadyInUse.into());
  60. }
  61. if !rent.is_exempt(new_account_info.lamports(), new_account_info_data_len) {
  62. return Err(TokenError::NotRentExempt.into());
  63. }
  64. if *mint_info.key != crate::native_mint::id() {
  65. let mut mint_info_data = mint_info.data.borrow_mut();
  66. let _: &mut Mint = state::unpack(&mut mint_info_data)
  67. .map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
  68. }
  69. account.mint = *mint_info.key;
  70. account.owner = *owner_info.key;
  71. account.delegate = COption::None;
  72. account.delegated_amount = 0;
  73. account.state = AccountState::Initialized;
  74. if *mint_info.key == crate::native_mint::id() {
  75. let rent_exempt_reserve = rent.minimum_balance(new_account_info_data_len);
  76. account.is_native = COption::Some(rent_exempt_reserve);
  77. account.amount = new_account_info
  78. .lamports()
  79. .checked_sub(rent_exempt_reserve)
  80. .ok_or(TokenError::Overflow)?;
  81. } else {
  82. account.is_native = COption::None;
  83. account.amount = 0;
  84. };
  85. Ok(())
  86. }
  87. /// Processes a [InitializeMultisig](enum.TokenInstruction.html) instruction.
  88. pub fn process_initialize_multisig(accounts: &[AccountInfo], m: u8) -> ProgramResult {
  89. let account_info_iter = &mut accounts.iter();
  90. let multisig_info = next_account_info(account_info_iter)?;
  91. let multisig_info_data_len = multisig_info.data_len();
  92. let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
  93. let mut multisig_account_data = multisig_info.data.borrow_mut();
  94. let mut multisig: &mut Multisig = state::unpack_unchecked(&mut multisig_account_data)?;
  95. if multisig.is_initialized {
  96. return Err(TokenError::AlreadyInUse.into());
  97. }
  98. if !rent.is_exempt(multisig_info.lamports(), multisig_info_data_len) {
  99. return Err(TokenError::NotRentExempt.into());
  100. }
  101. let signer_infos = account_info_iter.as_slice();
  102. multisig.m = m;
  103. multisig.n = signer_infos.len() as u8;
  104. if !is_valid_signer_index(multisig.n as usize) {
  105. return Err(TokenError::InvalidNumberOfProvidedSigners.into());
  106. }
  107. if !is_valid_signer_index(multisig.m as usize) {
  108. return Err(TokenError::InvalidNumberOfRequiredSigners.into());
  109. }
  110. for (i, signer_info) in signer_infos.iter().enumerate() {
  111. multisig.signers[i] = *signer_info.key;
  112. }
  113. multisig.is_initialized = true;
  114. Ok(())
  115. }
  116. /// Processes a [Transfer](enum.TokenInstruction.html) instruction.
  117. pub fn process_transfer(
  118. program_id: &Pubkey,
  119. accounts: &[AccountInfo],
  120. amount: u64,
  121. expected_decimals: Option<u8>,
  122. ) -> ProgramResult {
  123. let account_info_iter = &mut accounts.iter();
  124. let source_account_info = next_account_info(account_info_iter)?;
  125. let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
  126. Some((next_account_info(account_info_iter)?, expected_decimals))
  127. } else {
  128. None
  129. };
  130. let dest_account_info = next_account_info(account_info_iter)?;
  131. let authority_info = next_account_info(account_info_iter)?;
  132. if source_account_info.key == dest_account_info.key {
  133. return Ok(());
  134. }
  135. let mut source_data = source_account_info.data.borrow_mut();
  136. let mut source_account: &mut Account = state::unpack(&mut source_data)?;
  137. let mut dest_data = dest_account_info.data.borrow_mut();
  138. let mut dest_account: &mut Account = state::unpack(&mut dest_data)?;
  139. if source_account.amount < amount {
  140. return Err(TokenError::InsufficientFunds.into());
  141. }
  142. if source_account.mint != dest_account.mint {
  143. return Err(TokenError::MintMismatch.into());
  144. }
  145. if source_account.is_frozen() || dest_account.is_frozen() {
  146. return Err(TokenError::AccountFrozen.into());
  147. }
  148. if let Some((mint_account_info, expected_decimals)) = expected_mint_info {
  149. if source_account.mint != *mint_account_info.key {
  150. return Err(TokenError::MintMismatch.into());
  151. }
  152. let mut mint_info_data = mint_account_info.data.borrow_mut();
  153. let mint: &Mint = state::unpack_unchecked(&mut mint_info_data)?;
  154. if expected_decimals != mint.decimals {
  155. return Err(TokenError::MintDecimalsMismatch.into());
  156. }
  157. }
  158. match source_account.delegate {
  159. COption::Some(ref delegate) if authority_info.key == delegate => {
  160. Self::validate_owner(
  161. program_id,
  162. delegate,
  163. authority_info,
  164. account_info_iter.as_slice(),
  165. )?;
  166. if source_account.delegated_amount < amount {
  167. return Err(TokenError::InsufficientFunds.into());
  168. }
  169. source_account.delegated_amount = source_account
  170. .delegated_amount
  171. .checked_sub(amount)
  172. .ok_or(TokenError::Overflow)?;
  173. if source_account.delegated_amount == 0 {
  174. source_account.delegate = COption::None;
  175. }
  176. }
  177. _ => Self::validate_owner(
  178. program_id,
  179. &source_account.owner,
  180. authority_info,
  181. account_info_iter.as_slice(),
  182. )?,
  183. };
  184. source_account.amount = source_account
  185. .amount
  186. .checked_sub(amount)
  187. .ok_or(TokenError::Overflow)?;
  188. dest_account.amount = dest_account
  189. .amount
  190. .checked_add(amount)
  191. .ok_or(TokenError::Overflow)?;
  192. if source_account.is_native() {
  193. let source_starting_lamports = source_account_info.lamports();
  194. **source_account_info.lamports.borrow_mut() = source_starting_lamports
  195. .checked_sub(amount)
  196. .ok_or(TokenError::Overflow)?;
  197. let dest_starting_lamports = dest_account_info.lamports();
  198. **dest_account_info.lamports.borrow_mut() = dest_starting_lamports
  199. .checked_add(amount)
  200. .ok_or(TokenError::Overflow)?;
  201. }
  202. Ok(())
  203. }
  204. /// Processes an [Approve](enum.TokenInstruction.html) instruction.
  205. pub fn process_approve(
  206. program_id: &Pubkey,
  207. accounts: &[AccountInfo],
  208. amount: u64,
  209. expected_decimals: Option<u8>,
  210. ) -> ProgramResult {
  211. let account_info_iter = &mut accounts.iter();
  212. let source_account_info = next_account_info(account_info_iter)?;
  213. let expected_mint_info = if let Some(expected_decimals) = expected_decimals {
  214. Some((next_account_info(account_info_iter)?, expected_decimals))
  215. } else {
  216. None
  217. };
  218. let delegate_info = next_account_info(account_info_iter)?;
  219. let owner_info = next_account_info(account_info_iter)?;
  220. let mut source_data = source_account_info.data.borrow_mut();
  221. let mut source_account: &mut Account = state::unpack(&mut source_data)?;
  222. if source_account.is_frozen() {
  223. return Err(TokenError::AccountFrozen.into());
  224. }
  225. if let Some((mint_account_info, expected_decimals)) = expected_mint_info {
  226. if source_account.mint != *mint_account_info.key {
  227. return Err(TokenError::MintMismatch.into());
  228. }
  229. let mut mint_info_data = mint_account_info.data.borrow_mut();
  230. let mint: &Mint = state::unpack_unchecked(&mut mint_info_data)?;
  231. if expected_decimals != mint.decimals {
  232. return Err(TokenError::MintDecimalsMismatch.into());
  233. }
  234. }
  235. Self::validate_owner(
  236. program_id,
  237. &source_account.owner,
  238. owner_info,
  239. account_info_iter.as_slice(),
  240. )?;
  241. source_account.delegate = COption::Some(*delegate_info.key);
  242. source_account.delegated_amount = amount;
  243. Ok(())
  244. }
  245. /// Processes an [Revoke](enum.TokenInstruction.html) instruction.
  246. pub fn process_revoke(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
  247. let account_info_iter = &mut accounts.iter();
  248. let source_account_info = next_account_info(account_info_iter)?;
  249. let mut source_data = source_account_info.data.borrow_mut();
  250. let mut source_account: &mut Account = state::unpack(&mut source_data)?;
  251. let owner_info = next_account_info(account_info_iter)?;
  252. if source_account.is_frozen() {
  253. return Err(TokenError::AccountFrozen.into());
  254. }
  255. Self::validate_owner(
  256. program_id,
  257. &source_account.owner,
  258. owner_info,
  259. account_info_iter.as_slice(),
  260. )?;
  261. source_account.delegate = COption::None;
  262. source_account.delegated_amount = 0;
  263. Ok(())
  264. }
  265. /// Processes a [SetAuthority](enum.TokenInstruction.html) instruction.
  266. pub fn process_set_authority(
  267. program_id: &Pubkey,
  268. accounts: &[AccountInfo],
  269. authority_type: AuthorityType,
  270. new_authority: COption<Pubkey>,
  271. ) -> ProgramResult {
  272. let account_info_iter = &mut accounts.iter();
  273. let account_info = next_account_info(account_info_iter)?;
  274. let authority_info = next_account_info(account_info_iter)?;
  275. if account_info.data_len() == size_of::<Account>() {
  276. let mut account_data = account_info.data.borrow_mut();
  277. let mut account: &mut Account = state::unpack(&mut account_data)?;
  278. if account.is_frozen() {
  279. return Err(TokenError::AccountFrozen.into());
  280. }
  281. match authority_type {
  282. AuthorityType::AccountHolder => {
  283. Self::validate_owner(
  284. program_id,
  285. &account.owner,
  286. authority_info,
  287. account_info_iter.as_slice(),
  288. )?;
  289. if let COption::Some(authority) = new_authority {
  290. account.owner = authority;
  291. } else {
  292. return Err(TokenError::InvalidInstruction.into());
  293. }
  294. }
  295. AuthorityType::CloseAccount => {
  296. let authority = account.close_authority.unwrap_or(account.owner);
  297. Self::validate_owner(
  298. program_id,
  299. &authority,
  300. authority_info,
  301. account_info_iter.as_slice(),
  302. )?;
  303. account.close_authority = new_authority;
  304. }
  305. _ => {
  306. return Err(TokenError::AuthorityTypeNotSupported.into());
  307. }
  308. }
  309. } else if account_info.data_len() == size_of::<Mint>() {
  310. let mut account_data = account_info.data.borrow_mut();
  311. let mut mint: &mut Mint = state::unpack(&mut account_data)?;
  312. match authority_type {
  313. AuthorityType::MintTokens => {
  314. // Once a mint's supply is fixed, it cannot be undone by setting a new
  315. // mint_authority
  316. let mint_authority = mint
  317. .mint_authority
  318. .ok_or(Into::<ProgramError>::into(TokenError::FixedSupply))?;
  319. Self::validate_owner(
  320. program_id,
  321. &mint_authority,
  322. authority_info,
  323. account_info_iter.as_slice(),
  324. )?;
  325. mint.mint_authority = new_authority;
  326. }
  327. AuthorityType::FreezeAccount => {
  328. // Once a mint's freeze authority is disabled, it cannot be re-enabled by
  329. // setting a new freeze_authority
  330. let freeze_authority = mint
  331. .freeze_authority
  332. .ok_or(Into::<ProgramError>::into(TokenError::MintCannotFreeze))?;
  333. Self::validate_owner(
  334. program_id,
  335. &freeze_authority,
  336. authority_info,
  337. account_info_iter.as_slice(),
  338. )?;
  339. mint.freeze_authority = new_authority;
  340. }
  341. _ => {
  342. return Err(TokenError::AuthorityTypeNotSupported.into());
  343. }
  344. }
  345. } else {
  346. return Err(ProgramError::InvalidArgument);
  347. }
  348. Ok(())
  349. }
  350. /// Processes a [MintTo](enum.TokenInstruction.html) instruction.
  351. pub fn process_mint_to(
  352. program_id: &Pubkey,
  353. accounts: &[AccountInfo],
  354. amount: u64,
  355. expected_decimals: Option<u8>,
  356. ) -> ProgramResult {
  357. let account_info_iter = &mut accounts.iter();
  358. let mint_info = next_account_info(account_info_iter)?;
  359. let dest_account_info = next_account_info(account_info_iter)?;
  360. let owner_info = next_account_info(account_info_iter)?;
  361. let mut dest_account_data = dest_account_info.data.borrow_mut();
  362. let mut dest_account: &mut Account = state::unpack(&mut dest_account_data)?;
  363. if dest_account.is_frozen() {
  364. return Err(TokenError::AccountFrozen.into());
  365. }
  366. if dest_account.is_native() {
  367. return Err(TokenError::NativeNotSupported.into());
  368. }
  369. if mint_info.key != &dest_account.mint {
  370. return Err(TokenError::MintMismatch.into());
  371. }
  372. let mut mint_info_data = mint_info.data.borrow_mut();
  373. let mint: &mut Mint = state::unpack(&mut mint_info_data)?;
  374. if let Some(expected_decimals) = expected_decimals {
  375. if expected_decimals != mint.decimals {
  376. return Err(TokenError::MintDecimalsMismatch.into());
  377. }
  378. }
  379. match mint.mint_authority {
  380. COption::Some(mint_authority) => {
  381. Self::validate_owner(
  382. program_id,
  383. &mint_authority,
  384. owner_info,
  385. account_info_iter.as_slice(),
  386. )?;
  387. }
  388. COption::None => {
  389. return Err(TokenError::FixedSupply.into());
  390. }
  391. }
  392. dest_account.amount = dest_account
  393. .amount
  394. .checked_add(amount)
  395. .ok_or(TokenError::Overflow)?;
  396. mint.supply = mint
  397. .supply
  398. .checked_add(amount)
  399. .ok_or(TokenError::Overflow)?;
  400. Ok(())
  401. }
  402. /// Processes a [Burn](enum.TokenInstruction.html) instruction.
  403. pub fn process_burn(
  404. program_id: &Pubkey,
  405. accounts: &[AccountInfo],
  406. amount: u64,
  407. expected_decimals: Option<u8>,
  408. ) -> ProgramResult {
  409. let account_info_iter = &mut accounts.iter();
  410. let source_account_info = next_account_info(account_info_iter)?;
  411. let mint_info = next_account_info(account_info_iter)?;
  412. let authority_info = next_account_info(account_info_iter)?;
  413. let mut mint_data = mint_info.data.borrow_mut();
  414. let mint: &mut Mint = state::unpack(&mut mint_data)?;
  415. let mut source_data = source_account_info.data.borrow_mut();
  416. let source_account: &mut Account = state::unpack(&mut source_data)?;
  417. if source_account.is_native() {
  418. return Err(TokenError::NativeNotSupported.into());
  419. }
  420. if mint_info.key != &source_account.mint {
  421. return Err(TokenError::MintMismatch.into());
  422. }
  423. if source_account.amount < amount {
  424. return Err(TokenError::InsufficientFunds.into());
  425. }
  426. if source_account.is_frozen() {
  427. return Err(TokenError::AccountFrozen.into());
  428. }
  429. if let Some(expected_decimals) = expected_decimals {
  430. if expected_decimals != mint.decimals {
  431. return Err(TokenError::MintDecimalsMismatch.into());
  432. }
  433. }
  434. match source_account.delegate {
  435. COption::Some(ref delegate) if authority_info.key == delegate => {
  436. Self::validate_owner(
  437. program_id,
  438. delegate,
  439. authority_info,
  440. account_info_iter.as_slice(),
  441. )?;
  442. if source_account.delegated_amount < amount {
  443. return Err(TokenError::InsufficientFunds.into());
  444. }
  445. source_account.delegated_amount = source_account
  446. .delegated_amount
  447. .checked_sub(amount)
  448. .ok_or(TokenError::Overflow)?;
  449. if source_account.delegated_amount == 0 {
  450. source_account.delegate = COption::None;
  451. }
  452. }
  453. _ => Self::validate_owner(
  454. program_id,
  455. &source_account.owner,
  456. authority_info,
  457. account_info_iter.as_slice(),
  458. )?,
  459. }
  460. source_account.amount = source_account
  461. .amount
  462. .checked_sub(amount)
  463. .ok_or(TokenError::Overflow)?;
  464. mint.supply = mint
  465. .supply
  466. .checked_sub(amount)
  467. .ok_or(TokenError::Overflow)?;
  468. Ok(())
  469. }
  470. /// Processes a [CloseAccount](enum.TokenInstruction.html) instruction.
  471. pub fn process_close_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
  472. let account_info_iter = &mut accounts.iter();
  473. let source_account_info = next_account_info(account_info_iter)?;
  474. let dest_account_info = next_account_info(account_info_iter)?;
  475. let authority_info = next_account_info(account_info_iter)?;
  476. let mut source_data = source_account_info.data.borrow_mut();
  477. let source_account: &mut Account = state::unpack(&mut source_data)?;
  478. if !source_account.is_native() && source_account.amount != 0 {
  479. return Err(TokenError::NonNativeHasBalance.into());
  480. }
  481. let authority = source_account
  482. .close_authority
  483. .unwrap_or(source_account.owner);
  484. Self::validate_owner(
  485. program_id,
  486. &authority,
  487. authority_info,
  488. account_info_iter.as_slice(),
  489. )?;
  490. let dest_starting_lamports = dest_account_info.lamports();
  491. **dest_account_info.lamports.borrow_mut() = dest_starting_lamports
  492. .checked_add(source_account_info.lamports())
  493. .ok_or(TokenError::Overflow)?;
  494. **source_account_info.lamports.borrow_mut() = 0;
  495. source_account.amount = 0;
  496. Ok(())
  497. }
  498. /// Processes a [FreezeAccount](enum.TokenInstruction.html) or a
  499. /// [ThawAccount](enum.TokenInstruction.html) instruction.
  500. pub fn process_toggle_freeze_account(
  501. program_id: &Pubkey,
  502. accounts: &[AccountInfo],
  503. freeze: bool,
  504. ) -> ProgramResult {
  505. let account_info_iter = &mut accounts.iter();
  506. let source_account_info = next_account_info(account_info_iter)?;
  507. let mint_info = next_account_info(account_info_iter)?;
  508. let authority_info = next_account_info(account_info_iter)?;
  509. let mut source_data = source_account_info.data.borrow_mut();
  510. let source_account: &mut Account = state::unpack(&mut source_data)?;
  511. if source_account.is_native() {
  512. return Err(TokenError::NativeNotSupported.into());
  513. }
  514. if mint_info.key != &source_account.mint {
  515. return Err(TokenError::MintMismatch.into());
  516. }
  517. if freeze && source_account.is_frozen() || !freeze && !source_account.is_frozen() {
  518. return Err(TokenError::InvalidState.into());
  519. }
  520. let mut mint_info_data = mint_info.data.borrow_mut();
  521. let mint: &mut Mint = state::unpack(&mut mint_info_data)?;
  522. match mint.freeze_authority {
  523. COption::Some(authority) => {
  524. Self::validate_owner(
  525. program_id,
  526. &authority,
  527. authority_info,
  528. account_info_iter.as_slice(),
  529. )?;
  530. }
  531. COption::None => {
  532. return Err(TokenError::MintCannotFreeze.into());
  533. }
  534. }
  535. source_account.state = if freeze {
  536. AccountState::Frozen
  537. } else {
  538. AccountState::Initialized
  539. };
  540. Ok(())
  541. }
  542. /// Processes an [Instruction](enum.Instruction.html).
  543. pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
  544. let instruction = TokenInstruction::unpack(input)?;
  545. match instruction {
  546. TokenInstruction::InitializeMint {
  547. decimals,
  548. mint_authority,
  549. freeze_authority,
  550. } => {
  551. info!("Instruction: InitializeMint");
  552. Self::process_initialize_mint(accounts, decimals, mint_authority, freeze_authority)
  553. }
  554. TokenInstruction::InitializeAccount => {
  555. info!("Instruction: InitializeAccount");
  556. Self::process_initialize_account(accounts)
  557. }
  558. TokenInstruction::InitializeMultisig { m } => {
  559. info!("Instruction: InitializeMultisig");
  560. Self::process_initialize_multisig(accounts, m)
  561. }
  562. TokenInstruction::Transfer { amount } => {
  563. info!("Instruction: Transfer");
  564. Self::process_transfer(program_id, accounts, amount, None)
  565. }
  566. TokenInstruction::Approve { amount } => {
  567. info!("Instruction: Approve");
  568. Self::process_approve(program_id, accounts, amount, None)
  569. }
  570. TokenInstruction::Revoke => {
  571. info!("Instruction: Revoke");
  572. Self::process_revoke(program_id, accounts)
  573. }
  574. TokenInstruction::SetAuthority {
  575. authority_type,
  576. new_authority,
  577. } => {
  578. info!("Instruction: SetAuthority");
  579. Self::process_set_authority(program_id, accounts, authority_type, new_authority)
  580. }
  581. TokenInstruction::MintTo { amount } => {
  582. info!("Instruction: MintTo");
  583. Self::process_mint_to(program_id, accounts, amount, None)
  584. }
  585. TokenInstruction::Burn { amount } => {
  586. info!("Instruction: Burn");
  587. Self::process_burn(program_id, accounts, amount, None)
  588. }
  589. TokenInstruction::CloseAccount => {
  590. info!("Instruction: CloseAccount");
  591. Self::process_close_account(program_id, accounts)
  592. }
  593. TokenInstruction::FreezeAccount => {
  594. info!("Instruction: FreezeAccount");
  595. Self::process_toggle_freeze_account(program_id, accounts, true)
  596. }
  597. TokenInstruction::ThawAccount => {
  598. info!("Instruction: FreezeAccount");
  599. Self::process_toggle_freeze_account(program_id, accounts, false)
  600. }
  601. TokenInstruction::Transfer2 { amount, decimals } => {
  602. info!("Instruction: Transfer");
  603. Self::process_transfer(program_id, accounts, amount, Some(decimals))
  604. }
  605. TokenInstruction::Approve2 { amount, decimals } => {
  606. info!("Instruction: Approve");
  607. Self::process_approve(program_id, accounts, amount, Some(decimals))
  608. }
  609. TokenInstruction::MintTo2 { amount, decimals } => {
  610. info!("Instruction: MintTo");
  611. Self::process_mint_to(program_id, accounts, amount, Some(decimals))
  612. }
  613. TokenInstruction::Burn2 { amount, decimals } => {
  614. info!("Instruction: Burn");
  615. Self::process_burn(program_id, accounts, amount, Some(decimals))
  616. }
  617. }
  618. }
  619. /// Validates owner(s) are present
  620. pub fn validate_owner(
  621. program_id: &Pubkey,
  622. expected_owner: &Pubkey,
  623. owner_account_info: &AccountInfo,
  624. signers: &[AccountInfo],
  625. ) -> ProgramResult {
  626. if expected_owner != owner_account_info.key {
  627. return Err(TokenError::OwnerMismatch.into());
  628. }
  629. if program_id == owner_account_info.owner
  630. && owner_account_info.data_len() == std::mem::size_of::<Multisig>()
  631. {
  632. let mut owner_data = owner_account_info.data.borrow_mut();
  633. let multisig: &mut Multisig = state::unpack(&mut owner_data)?;
  634. let mut num_signers = 0;
  635. for signer in signers.iter() {
  636. if multisig.signers[0..multisig.n as usize].contains(signer.key) {
  637. if !signer.is_signer {
  638. return Err(ProgramError::MissingRequiredSignature);
  639. }
  640. num_signers += 1;
  641. }
  642. }
  643. if num_signers < multisig.m {
  644. return Err(ProgramError::MissingRequiredSignature);
  645. }
  646. } else if !owner_account_info.is_signer {
  647. return Err(ProgramError::MissingRequiredSignature);
  648. }
  649. Ok(())
  650. }
  651. }
  652. impl PrintProgramError for TokenError {
  653. fn print<E>(&self)
  654. where
  655. E: 'static + std::error::Error + DecodeError<E> + PrintProgramError + FromPrimitive,
  656. {
  657. match self {
  658. TokenError::NotRentExempt => {
  659. info!("Error: Lamport balance below rent-exempt threshold")
  660. }
  661. TokenError::InsufficientFunds => info!("Error: insufficient funds"),
  662. TokenError::InvalidMint => info!("Error: Invalid Mint"),
  663. TokenError::MintMismatch => info!("Error: Account not associated with this Mint"),
  664. TokenError::OwnerMismatch => info!("Error: owner does not match"),
  665. TokenError::FixedSupply => info!("Error: the total supply of this token is fixed"),
  666. TokenError::AlreadyInUse => info!("Error: account or token already in use"),
  667. TokenError::InvalidNumberOfProvidedSigners => {
  668. info!("Error: Invalid number of provided signers")
  669. }
  670. TokenError::InvalidNumberOfRequiredSigners => {
  671. info!("Error: Invalid number of required signers")
  672. }
  673. TokenError::UninitializedState => info!("Error: State is uninitialized"),
  674. TokenError::NativeNotSupported => {
  675. info!("Error: Instruction does not support native tokens")
  676. }
  677. TokenError::NonNativeHasBalance => {
  678. info!("Error: Non-native account can only be closed if its balance is zero")
  679. }
  680. TokenError::InvalidInstruction => info!("Error: Invalid instruction"),
  681. TokenError::InvalidState => info!("Error: Invalid account state for operation"),
  682. TokenError::Overflow => info!("Error: Operation overflowed"),
  683. TokenError::AuthorityTypeNotSupported => {
  684. info!("Error: Account does not support specified authority type")
  685. }
  686. TokenError::MintCannotFreeze => info!("Error: This token mint cannot freeze accounts"),
  687. TokenError::AccountFrozen => info!("Error: Account is frozen"),
  688. TokenError::MintDecimalsMismatch => {
  689. info!("Error: decimals different from the Mint decimals")
  690. }
  691. }
  692. }
  693. }
  694. // Pull in syscall stubs when building for non-BPF targets
  695. #[cfg(not(target_arch = "bpf"))]
  696. solana_sdk::program_stubs!();
  697. #[cfg(test)]
  698. mod tests {
  699. use super::*;
  700. use crate::instruction::*;
  701. use solana_sdk::{
  702. account::Account as SolanaAccount, account_info::create_is_signer_account_infos,
  703. clock::Epoch, instruction::Instruction, sysvar::rent,
  704. };
  705. fn pubkey_rand() -> Pubkey {
  706. Pubkey::new(&rand::random::<[u8; 32]>())
  707. }
  708. fn do_process_instruction(
  709. instruction: Instruction,
  710. accounts: Vec<&mut SolanaAccount>,
  711. ) -> ProgramResult {
  712. let mut meta = instruction
  713. .accounts
  714. .iter()
  715. .zip(accounts)
  716. .map(|(account_meta, account)| (&account_meta.pubkey, account_meta.is_signer, account))
  717. .collect::<Vec<_>>();
  718. let account_infos = create_is_signer_account_infos(&mut meta);
  719. Processor::process(&instruction.program_id, &account_infos, &instruction.data)
  720. }
  721. fn return_token_error_as_program_error() -> ProgramError {
  722. TokenError::MintMismatch.into()
  723. }
  724. fn rent_sysvar() -> SolanaAccount {
  725. rent::create_account(42, &Rent::default())
  726. }
  727. fn mint_minimum_balance() -> u64 {
  728. Rent::default().minimum_balance(size_of::<Mint>())
  729. }
  730. fn account_minimum_balance() -> u64 {
  731. Rent::default().minimum_balance(size_of::<Account>())
  732. }
  733. fn multisig_minimum_balance() -> u64 {
  734. Rent::default().minimum_balance(size_of::<Multisig>())
  735. }
  736. #[test]
  737. fn test_print_error() {
  738. let error = return_token_error_as_program_error();
  739. error.print::<TokenError>();
  740. }
  741. #[test]
  742. #[should_panic(expected = "Custom(3)")]
  743. fn test_error_unwrap() {
  744. Err::<(), ProgramError>(return_token_error_as_program_error()).unwrap();
  745. }
  746. #[test]
  747. fn test_unique_account_sizes() {
  748. assert_ne!(size_of::<Mint>(), 0);
  749. assert_ne!(size_of::<Mint>(), size_of::<Account>());
  750. assert_ne!(size_of::<Mint>(), size_of::<Multisig>());
  751. assert_ne!(size_of::<Account>(), 0);
  752. assert_ne!(size_of::<Account>(), size_of::<Multisig>());
  753. assert_ne!(size_of::<Multisig>(), 0);
  754. }
  755. #[test]
  756. fn test_initialize_mint() {
  757. let program_id = pubkey_rand();
  758. let owner_key = pubkey_rand();
  759. let mint_key = pubkey_rand();
  760. let mut mint_account = SolanaAccount::new(42, size_of::<Mint>(), &program_id);
  761. let mint2_key = pubkey_rand();
  762. let mut mint2_account =
  763. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  764. let mut rent_sysvar = rent_sysvar();
  765. // mint is not rent exempt
  766. assert_eq!(
  767. Err(TokenError::NotRentExempt.into()),
  768. do_process_instruction(
  769. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  770. vec![&mut mint_account, &mut rent_sysvar]
  771. )
  772. );
  773. mint_account.lamports = mint_minimum_balance();
  774. // create new mint
  775. do_process_instruction(
  776. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  777. vec![&mut mint_account, &mut rent_sysvar],
  778. )
  779. .unwrap();
  780. // create twice
  781. assert_eq!(
  782. Err(TokenError::AlreadyInUse.into()),
  783. do_process_instruction(
  784. initialize_mint(&program_id, &mint_key, &owner_key, None, 2,).unwrap(),
  785. vec![&mut mint_account, &mut rent_sysvar]
  786. )
  787. );
  788. // create another mint that can freeze
  789. do_process_instruction(
  790. initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
  791. vec![&mut mint2_account, &mut rent_sysvar],
  792. )
  793. .unwrap();
  794. let mint2: &mut Mint = state::unpack(&mut mint2_account.data).unwrap();
  795. assert_eq!(mint2.freeze_authority, COption::Some(owner_key));
  796. }
  797. #[test]
  798. fn test_initialize_mint_account() {
  799. let program_id = pubkey_rand();
  800. let account_key = pubkey_rand();
  801. let mut account_account = SolanaAccount::new(42, size_of::<Account>(), &program_id);
  802. let owner_key = pubkey_rand();
  803. let mut owner_account = SolanaAccount::default();
  804. let mint_key = pubkey_rand();
  805. let mut mint_account =
  806. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  807. let mut rent_sysvar = rent_sysvar();
  808. // account is not rent exempt
  809. assert_eq!(
  810. Err(TokenError::NotRentExempt.into()),
  811. do_process_instruction(
  812. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  813. vec![
  814. &mut account_account,
  815. &mut mint_account,
  816. &mut owner_account,
  817. &mut rent_sysvar
  818. ],
  819. )
  820. );
  821. account_account.lamports = account_minimum_balance();
  822. // mint is not valid (not initialized)
  823. assert_eq!(
  824. Err(TokenError::InvalidMint.into()),
  825. do_process_instruction(
  826. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  827. vec![
  828. &mut account_account,
  829. &mut mint_account,
  830. &mut owner_account,
  831. &mut rent_sysvar
  832. ],
  833. )
  834. );
  835. // create mint
  836. do_process_instruction(
  837. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  838. vec![&mut mint_account, &mut rent_sysvar],
  839. )
  840. .unwrap();
  841. // create account
  842. do_process_instruction(
  843. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  844. vec![
  845. &mut account_account,
  846. &mut mint_account,
  847. &mut owner_account,
  848. &mut rent_sysvar,
  849. ],
  850. )
  851. .unwrap();
  852. // create twice
  853. assert_eq!(
  854. Err(TokenError::AlreadyInUse.into()),
  855. do_process_instruction(
  856. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  857. vec![
  858. &mut account_account,
  859. &mut mint_account,
  860. &mut owner_account,
  861. &mut rent_sysvar
  862. ],
  863. )
  864. );
  865. }
  866. #[test]
  867. fn test_transfer() {
  868. let program_id = pubkey_rand();
  869. let account_key = pubkey_rand();
  870. let mut account_account =
  871. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  872. let account2_key = pubkey_rand();
  873. let mut account2_account =
  874. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  875. let account3_key = pubkey_rand();
  876. let mut account3_account =
  877. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  878. let delegate_key = pubkey_rand();
  879. let mut delegate_account = SolanaAccount::default();
  880. let mismatch_key = pubkey_rand();
  881. let mut mismatch_account =
  882. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  883. let owner_key = pubkey_rand();
  884. let mut owner_account = SolanaAccount::default();
  885. let owner2_key = pubkey_rand();
  886. let mut owner2_account = SolanaAccount::default();
  887. let mint_key = pubkey_rand();
  888. let mut mint_account =
  889. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  890. let mint2_key = pubkey_rand();
  891. let mut rent_sysvar = rent_sysvar();
  892. // create mint
  893. do_process_instruction(
  894. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  895. vec![&mut mint_account, &mut rent_sysvar],
  896. )
  897. .unwrap();
  898. // create account
  899. do_process_instruction(
  900. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  901. vec![
  902. &mut account_account,
  903. &mut mint_account,
  904. &mut owner_account,
  905. &mut rent_sysvar,
  906. ],
  907. )
  908. .unwrap();
  909. // create another account
  910. do_process_instruction(
  911. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  912. vec![
  913. &mut account2_account,
  914. &mut mint_account,
  915. &mut owner_account,
  916. &mut rent_sysvar,
  917. ],
  918. )
  919. .unwrap();
  920. // create another account
  921. do_process_instruction(
  922. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  923. vec![
  924. &mut account3_account,
  925. &mut mint_account,
  926. &mut owner_account,
  927. &mut rent_sysvar,
  928. ],
  929. )
  930. .unwrap();
  931. // create mismatch account
  932. do_process_instruction(
  933. initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
  934. vec![
  935. &mut mismatch_account,
  936. &mut mint_account,
  937. &mut owner_account,
  938. &mut rent_sysvar,
  939. ],
  940. )
  941. .unwrap();
  942. let account: &mut Account = state::unpack(&mut mismatch_account.data).unwrap();
  943. account.mint = mint2_key;
  944. // mint to account
  945. do_process_instruction(
  946. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  947. vec![&mut mint_account, &mut account_account, &mut owner_account],
  948. )
  949. .unwrap();
  950. // missing signer
  951. let mut instruction = transfer(
  952. &program_id,
  953. &account_key,
  954. &account2_key,
  955. &owner_key,
  956. &[],
  957. 1000,
  958. )
  959. .unwrap();
  960. instruction.accounts[2].is_signer = false;
  961. assert_eq!(
  962. Err(ProgramError::MissingRequiredSignature),
  963. do_process_instruction(
  964. instruction,
  965. vec![
  966. &mut account_account,
  967. &mut account2_account,
  968. &mut owner_account,
  969. ],
  970. )
  971. );
  972. // mismatch mint
  973. assert_eq!(
  974. Err(TokenError::MintMismatch.into()),
  975. do_process_instruction(
  976. transfer(
  977. &program_id,
  978. &account_key,
  979. &mismatch_key,
  980. &owner_key,
  981. &[],
  982. 1000
  983. )
  984. .unwrap(),
  985. vec![
  986. &mut account_account,
  987. &mut mismatch_account,
  988. &mut owner_account,
  989. ],
  990. )
  991. );
  992. // missing owner
  993. assert_eq!(
  994. Err(TokenError::OwnerMismatch.into()),
  995. do_process_instruction(
  996. transfer(
  997. &program_id,
  998. &account_key,
  999. &account2_key,
  1000. &owner2_key,
  1001. &[],
  1002. 1000
  1003. )
  1004. .unwrap(),
  1005. vec![
  1006. &mut account_account,
  1007. &mut account2_account,
  1008. &mut owner2_account,
  1009. ],
  1010. )
  1011. );
  1012. // transfer
  1013. do_process_instruction(
  1014. transfer(
  1015. &program_id,
  1016. &account_key,
  1017. &account2_key,
  1018. &owner_key,
  1019. &[],
  1020. 1000,
  1021. )
  1022. .unwrap(),
  1023. vec![
  1024. &mut account_account,
  1025. &mut account2_account,
  1026. &mut owner_account,
  1027. ],
  1028. )
  1029. .unwrap();
  1030. // insufficient funds
  1031. assert_eq!(
  1032. Err(TokenError::InsufficientFunds.into()),
  1033. do_process_instruction(
  1034. transfer(&program_id, &account_key, &account2_key, &owner_key, &[], 1).unwrap(),
  1035. vec![
  1036. &mut account_account,
  1037. &mut account2_account,
  1038. &mut owner_account,
  1039. ],
  1040. )
  1041. );
  1042. // transfer half back
  1043. do_process_instruction(
  1044. transfer(
  1045. &program_id,
  1046. &account2_key,
  1047. &account_key,
  1048. &owner_key,
  1049. &[],
  1050. 500,
  1051. )
  1052. .unwrap(),
  1053. vec![
  1054. &mut account2_account,
  1055. &mut account_account,
  1056. &mut owner_account,
  1057. ],
  1058. )
  1059. .unwrap();
  1060. // incorrect decimals
  1061. assert_eq!(
  1062. Err(TokenError::MintDecimalsMismatch.into()),
  1063. do_process_instruction(
  1064. transfer2(
  1065. &program_id,
  1066. &account2_key,
  1067. &mint_key,
  1068. &account_key,
  1069. &owner_key,
  1070. &[],
  1071. 1,
  1072. 10 // <-- incorrect decimals
  1073. )
  1074. .unwrap(),
  1075. vec![
  1076. &mut account2_account,
  1077. &mut mint_account,
  1078. &mut account_account,
  1079. &mut owner_account,
  1080. ],
  1081. )
  1082. );
  1083. // incorrect mint
  1084. assert_eq!(
  1085. Err(TokenError::MintMismatch.into()),
  1086. do_process_instruction(
  1087. transfer2(
  1088. &program_id,
  1089. &account2_key,
  1090. &account3_key, // <-- incorrect mint
  1091. &account_key,
  1092. &owner_key,
  1093. &[],
  1094. 1,
  1095. 2
  1096. )
  1097. .unwrap(),
  1098. vec![
  1099. &mut account2_account,
  1100. &mut account3_account, // <-- incorrect mint
  1101. &mut account_account,
  1102. &mut owner_account,
  1103. ],
  1104. )
  1105. );
  1106. // transfer rest with explicit decimals
  1107. do_process_instruction(
  1108. transfer2(
  1109. &program_id,
  1110. &account2_key,
  1111. &mint_key,
  1112. &account_key,
  1113. &owner_key,
  1114. &[],
  1115. 500,
  1116. 2,
  1117. )
  1118. .unwrap(),
  1119. vec![
  1120. &mut account2_account,
  1121. &mut mint_account,
  1122. &mut account_account,
  1123. &mut owner_account,
  1124. ],
  1125. )
  1126. .unwrap();
  1127. // transfer to self
  1128. {
  1129. let instruction = transfer(
  1130. &program_id,
  1131. &account_key,
  1132. &account_key,
  1133. &owner_key,
  1134. &[],
  1135. 500,
  1136. )
  1137. .unwrap();
  1138. let account_account_info = AccountInfo::from((
  1139. &instruction.accounts[0].pubkey,
  1140. instruction.accounts[0].is_signer,
  1141. &mut account_account,
  1142. ));
  1143. let owner_account_info = AccountInfo::from((
  1144. &instruction.accounts[2].pubkey,
  1145. instruction.accounts[2].is_signer,
  1146. &mut owner_account,
  1147. ));
  1148. Processor::process(
  1149. &instruction.program_id,
  1150. &[
  1151. account_account_info.clone(),
  1152. account_account_info,
  1153. owner_account_info,
  1154. ],
  1155. &instruction.data,
  1156. )
  1157. .unwrap()
  1158. }
  1159. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  1160. assert_eq!(account.amount, 1000);
  1161. // insufficient funds
  1162. assert_eq!(
  1163. Err(TokenError::InsufficientFunds.into()),
  1164. do_process_instruction(
  1165. transfer(&program_id, &account2_key, &account_key, &owner_key, &[], 1).unwrap(),
  1166. vec![
  1167. &mut account2_account,
  1168. &mut account_account,
  1169. &mut owner_account,
  1170. ],
  1171. )
  1172. );
  1173. // approve delegate
  1174. do_process_instruction(
  1175. approve(
  1176. &program_id,
  1177. &account_key,
  1178. &delegate_key,
  1179. &owner_key,
  1180. &[],
  1181. 100,
  1182. )
  1183. .unwrap(),
  1184. vec![
  1185. &mut account_account,
  1186. &mut delegate_account,
  1187. &mut owner_account,
  1188. ],
  1189. )
  1190. .unwrap();
  1191. // transfer via delegate
  1192. do_process_instruction(
  1193. transfer(
  1194. &program_id,
  1195. &account_key,
  1196. &account2_key,
  1197. &delegate_key,
  1198. &[],
  1199. 100,
  1200. )
  1201. .unwrap(),
  1202. vec![
  1203. &mut account_account,
  1204. &mut account2_account,
  1205. &mut delegate_account,
  1206. ],
  1207. )
  1208. .unwrap();
  1209. // insufficient funds approved via delegate
  1210. assert_eq!(
  1211. Err(TokenError::OwnerMismatch.into()),
  1212. do_process_instruction(
  1213. transfer(
  1214. &program_id,
  1215. &account_key,
  1216. &account2_key,
  1217. &delegate_key,
  1218. &[],
  1219. 100
  1220. )
  1221. .unwrap(),
  1222. vec![
  1223. &mut account_account,
  1224. &mut account2_account,
  1225. &mut delegate_account,
  1226. ],
  1227. )
  1228. );
  1229. // transfer rest
  1230. do_process_instruction(
  1231. transfer(
  1232. &program_id,
  1233. &account_key,
  1234. &account2_key,
  1235. &owner_key,
  1236. &[],
  1237. 900,
  1238. )
  1239. .unwrap(),
  1240. vec![
  1241. &mut account_account,
  1242. &mut account2_account,
  1243. &mut owner_account,
  1244. ],
  1245. )
  1246. .unwrap();
  1247. // approve delegate
  1248. do_process_instruction(
  1249. approve(
  1250. &program_id,
  1251. &account_key,
  1252. &delegate_key,
  1253. &owner_key,
  1254. &[],
  1255. 100,
  1256. )
  1257. .unwrap(),
  1258. vec![
  1259. &mut account_account,
  1260. &mut delegate_account,
  1261. &mut owner_account,
  1262. ],
  1263. )
  1264. .unwrap();
  1265. // insufficient funds in source account via delegate
  1266. assert_eq!(
  1267. Err(TokenError::InsufficientFunds.into()),
  1268. do_process_instruction(
  1269. transfer(
  1270. &program_id,
  1271. &account_key,
  1272. &account2_key,
  1273. &delegate_key,
  1274. &[],
  1275. 100
  1276. )
  1277. .unwrap(),
  1278. vec![
  1279. &mut account_account,
  1280. &mut account2_account,
  1281. &mut delegate_account,
  1282. ],
  1283. )
  1284. );
  1285. }
  1286. #[test]
  1287. fn test_mintable_token_with_zero_supply() {
  1288. let program_id = pubkey_rand();
  1289. let account_key = pubkey_rand();
  1290. let mut account_account =
  1291. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1292. let owner_key = pubkey_rand();
  1293. let mut owner_account = SolanaAccount::default();
  1294. let mint_key = pubkey_rand();
  1295. let mut mint_account =
  1296. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  1297. let mut rent_sysvar = rent_sysvar();
  1298. // create mint-able token with zero supply
  1299. let decimals = 2;
  1300. do_process_instruction(
  1301. initialize_mint(&program_id, &mint_key, &owner_key, None, decimals).unwrap(),
  1302. vec![&mut mint_account, &mut rent_sysvar],
  1303. )
  1304. .unwrap();
  1305. let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  1306. assert_eq!(
  1307. *mint,
  1308. Mint {
  1309. mint_authority: COption::Some(owner_key),
  1310. supply: 0,
  1311. decimals,
  1312. is_initialized: true,
  1313. freeze_authority: COption::None,
  1314. }
  1315. );
  1316. // create account
  1317. do_process_instruction(
  1318. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1319. vec![
  1320. &mut account_account,
  1321. &mut mint_account,
  1322. &mut owner_account,
  1323. &mut rent_sysvar,
  1324. ],
  1325. )
  1326. .unwrap();
  1327. // mint to
  1328. do_process_instruction(
  1329. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
  1330. vec![&mut mint_account, &mut account_account, &mut owner_account],
  1331. )
  1332. .unwrap();
  1333. // mint to 2, with incorrect decimals
  1334. assert_eq!(
  1335. Err(TokenError::MintDecimalsMismatch.into()),
  1336. do_process_instruction(
  1337. mint_to2(
  1338. &program_id,
  1339. &mint_key,
  1340. &account_key,
  1341. &owner_key,
  1342. &[],
  1343. 42,
  1344. decimals + 1
  1345. )
  1346. .unwrap(),
  1347. vec![&mut mint_account, &mut account_account, &mut owner_account],
  1348. )
  1349. );
  1350. let _: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  1351. let dest_account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  1352. assert_eq!(dest_account.amount, 42);
  1353. // mint to 2
  1354. do_process_instruction(
  1355. mint_to2(
  1356. &program_id,
  1357. &mint_key,
  1358. &account_key,
  1359. &owner_key,
  1360. &[],
  1361. 42,
  1362. decimals,
  1363. )
  1364. .unwrap(),
  1365. vec![&mut mint_account, &mut account_account, &mut owner_account],
  1366. )
  1367. .unwrap();
  1368. let _: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  1369. let dest_account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  1370. assert_eq!(dest_account.amount, 84);
  1371. }
  1372. #[test]
  1373. fn test_approve() {
  1374. let program_id = pubkey_rand();
  1375. let account_key = pubkey_rand();
  1376. let mut account_account =
  1377. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1378. let account2_key = pubkey_rand();
  1379. let mut account2_account =
  1380. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1381. let delegate_key = pubkey_rand();
  1382. let mut delegate_account = SolanaAccount::default();
  1383. let owner_key = pubkey_rand();
  1384. let mut owner_account = SolanaAccount::default();
  1385. let owner2_key = pubkey_rand();
  1386. let mut owner2_account = SolanaAccount::default();
  1387. let mint_key = pubkey_rand();
  1388. let mut mint_account =
  1389. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  1390. let mut rent_sysvar = rent_sysvar();
  1391. // create mint
  1392. do_process_instruction(
  1393. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1394. vec![&mut mint_account, &mut rent_sysvar],
  1395. )
  1396. .unwrap();
  1397. // create account
  1398. do_process_instruction(
  1399. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1400. vec![
  1401. &mut account_account,
  1402. &mut mint_account,
  1403. &mut owner_account,
  1404. &mut rent_sysvar,
  1405. ],
  1406. )
  1407. .unwrap();
  1408. // create another account
  1409. do_process_instruction(
  1410. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  1411. vec![
  1412. &mut account2_account,
  1413. &mut mint_account,
  1414. &mut owner_account,
  1415. &mut rent_sysvar,
  1416. ],
  1417. )
  1418. .unwrap();
  1419. // mint to account
  1420. do_process_instruction(
  1421. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  1422. vec![&mut mint_account, &mut account_account, &mut owner_account],
  1423. )
  1424. .unwrap();
  1425. // missing signer
  1426. let mut instruction = approve(
  1427. &program_id,
  1428. &account_key,
  1429. &delegate_key,
  1430. &owner_key,
  1431. &[],
  1432. 100,
  1433. )
  1434. .unwrap();
  1435. instruction.accounts[2].is_signer = false;
  1436. assert_eq!(
  1437. Err(ProgramError::MissingRequiredSignature),
  1438. do_process_instruction(
  1439. instruction,
  1440. vec![
  1441. &mut account_account,
  1442. &mut delegate_account,
  1443. &mut owner_account,
  1444. ],
  1445. )
  1446. );
  1447. // no owner
  1448. assert_eq!(
  1449. Err(TokenError::OwnerMismatch.into()),
  1450. do_process_instruction(
  1451. approve(
  1452. &program_id,
  1453. &account_key,
  1454. &delegate_key,
  1455. &owner2_key,
  1456. &[],
  1457. 100
  1458. )
  1459. .unwrap(),
  1460. vec![
  1461. &mut account_account,
  1462. &mut delegate_account,
  1463. &mut owner2_account,
  1464. ],
  1465. )
  1466. );
  1467. // approve delegate
  1468. do_process_instruction(
  1469. approve(
  1470. &program_id,
  1471. &account_key,
  1472. &delegate_key,
  1473. &owner_key,
  1474. &[],
  1475. 100,
  1476. )
  1477. .unwrap(),
  1478. vec![
  1479. &mut account_account,
  1480. &mut delegate_account,
  1481. &mut owner_account,
  1482. ],
  1483. )
  1484. .unwrap();
  1485. // approve delegate 2, with incorrect decimals
  1486. assert_eq!(
  1487. Err(TokenError::MintDecimalsMismatch.into()),
  1488. do_process_instruction(
  1489. approve2(
  1490. &program_id,
  1491. &account_key,
  1492. &mint_key,
  1493. &delegate_key,
  1494. &owner_key,
  1495. &[],
  1496. 100,
  1497. 0 // <-- incorrect decimals
  1498. )
  1499. .unwrap(),
  1500. vec![
  1501. &mut account_account,
  1502. &mut mint_account,
  1503. &mut delegate_account,
  1504. &mut owner_account,
  1505. ],
  1506. )
  1507. );
  1508. // approve delegate 2, with incorrect mint
  1509. assert_eq!(
  1510. Err(TokenError::MintMismatch.into()),
  1511. do_process_instruction(
  1512. approve2(
  1513. &program_id,
  1514. &account_key,
  1515. &account2_key, // <-- bad mint
  1516. &delegate_key,
  1517. &owner_key,
  1518. &[],
  1519. 100,
  1520. 0
  1521. )
  1522. .unwrap(),
  1523. vec![
  1524. &mut account_account,
  1525. &mut account2_account, // <-- bad mint
  1526. &mut delegate_account,
  1527. &mut owner_account,
  1528. ],
  1529. )
  1530. );
  1531. // approve delegate 2
  1532. do_process_instruction(
  1533. approve2(
  1534. &program_id,
  1535. &account_key,
  1536. &mint_key,
  1537. &delegate_key,
  1538. &owner_key,
  1539. &[],
  1540. 100,
  1541. 2,
  1542. )
  1543. .unwrap(),
  1544. vec![
  1545. &mut account_account,
  1546. &mut mint_account,
  1547. &mut delegate_account,
  1548. &mut owner_account,
  1549. ],
  1550. )
  1551. .unwrap();
  1552. // revoke delegate
  1553. do_process_instruction(
  1554. revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
  1555. vec![&mut account_account, &mut owner_account],
  1556. )
  1557. .unwrap();
  1558. }
  1559. #[test]
  1560. fn test_set_authority() {
  1561. let program_id = pubkey_rand();
  1562. let account_key = pubkey_rand();
  1563. let mut account_account =
  1564. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1565. let account2_key = pubkey_rand();
  1566. let mut account2_account =
  1567. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1568. let owner_key = pubkey_rand();
  1569. let mut owner_account = SolanaAccount::default();
  1570. let owner2_key = pubkey_rand();
  1571. let mut owner2_account = SolanaAccount::default();
  1572. let owner3_key = pubkey_rand();
  1573. let mint_key = pubkey_rand();
  1574. let mut mint_account =
  1575. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  1576. let mint2_key = pubkey_rand();
  1577. let mut mint2_account =
  1578. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  1579. let mut rent_sysvar = rent_sysvar();
  1580. // create new mint with owner
  1581. do_process_instruction(
  1582. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1583. vec![&mut mint_account, &mut rent_sysvar],
  1584. )
  1585. .unwrap();
  1586. // create mint with owner and freeze_authority
  1587. do_process_instruction(
  1588. initialize_mint(&program_id, &mint2_key, &owner_key, Some(&owner_key), 2).unwrap(),
  1589. vec![&mut mint2_account, &mut rent_sysvar],
  1590. )
  1591. .unwrap();
  1592. // invalid account
  1593. assert_eq!(
  1594. Err(TokenError::UninitializedState.into()),
  1595. do_process_instruction(
  1596. set_authority(
  1597. &program_id,
  1598. &account_key,
  1599. Some(&owner2_key),
  1600. AuthorityType::AccountHolder,
  1601. &owner_key,
  1602. &[]
  1603. )
  1604. .unwrap(),
  1605. vec![&mut account_account, &mut owner_account],
  1606. )
  1607. );
  1608. // create account
  1609. do_process_instruction(
  1610. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1611. vec![
  1612. &mut account_account,
  1613. &mut mint_account,
  1614. &mut owner_account,
  1615. &mut rent_sysvar,
  1616. ],
  1617. )
  1618. .unwrap();
  1619. // create another account
  1620. do_process_instruction(
  1621. initialize_account(&program_id, &account2_key, &mint2_key, &owner_key).unwrap(),
  1622. vec![
  1623. &mut account2_account,
  1624. &mut mint2_account,
  1625. &mut owner_account,
  1626. &mut rent_sysvar,
  1627. ],
  1628. )
  1629. .unwrap();
  1630. // missing owner
  1631. assert_eq!(
  1632. Err(TokenError::OwnerMismatch.into()),
  1633. do_process_instruction(
  1634. set_authority(
  1635. &program_id,
  1636. &account_key,
  1637. Some(&owner_key),
  1638. AuthorityType::AccountHolder,
  1639. &owner2_key,
  1640. &[]
  1641. )
  1642. .unwrap(),
  1643. vec![&mut account_account, &mut owner2_account],
  1644. )
  1645. );
  1646. // owner did not sign
  1647. let mut instruction = set_authority(
  1648. &program_id,
  1649. &account_key,
  1650. Some(&owner2_key),
  1651. AuthorityType::AccountHolder,
  1652. &owner_key,
  1653. &[],
  1654. )
  1655. .unwrap();
  1656. instruction.accounts[1].is_signer = false;
  1657. assert_eq!(
  1658. Err(ProgramError::MissingRequiredSignature),
  1659. do_process_instruction(instruction, vec![&mut account_account, &mut owner_account,],)
  1660. );
  1661. // wrong authority type
  1662. assert_eq!(
  1663. Err(TokenError::AuthorityTypeNotSupported.into()),
  1664. do_process_instruction(
  1665. set_authority(
  1666. &program_id,
  1667. &account_key,
  1668. Some(&owner2_key),
  1669. AuthorityType::FreezeAccount,
  1670. &owner_key,
  1671. &[],
  1672. )
  1673. .unwrap(),
  1674. vec![&mut account_account, &mut owner_account],
  1675. )
  1676. );
  1677. // account owner may not be set to None
  1678. assert_eq!(
  1679. Err(TokenError::InvalidInstruction.into()),
  1680. do_process_instruction(
  1681. set_authority(
  1682. &program_id,
  1683. &account_key,
  1684. None,
  1685. AuthorityType::AccountHolder,
  1686. &owner_key,
  1687. &[],
  1688. )
  1689. .unwrap(),
  1690. vec![&mut account_account, &mut owner_account],
  1691. )
  1692. );
  1693. // set owner
  1694. do_process_instruction(
  1695. set_authority(
  1696. &program_id,
  1697. &account_key,
  1698. Some(&owner2_key),
  1699. AuthorityType::AccountHolder,
  1700. &owner_key,
  1701. &[],
  1702. )
  1703. .unwrap(),
  1704. vec![&mut account_account, &mut owner_account],
  1705. )
  1706. .unwrap();
  1707. // set close_authority
  1708. do_process_instruction(
  1709. set_authority(
  1710. &program_id,
  1711. &account_key,
  1712. Some(&owner2_key),
  1713. AuthorityType::CloseAccount,
  1714. &owner2_key,
  1715. &[],
  1716. )
  1717. .unwrap(),
  1718. vec![&mut account_account, &mut owner2_account],
  1719. )
  1720. .unwrap();
  1721. // close_authority may be set to None
  1722. do_process_instruction(
  1723. set_authority(
  1724. &program_id,
  1725. &account_key,
  1726. None,
  1727. AuthorityType::CloseAccount,
  1728. &owner2_key,
  1729. &[],
  1730. )
  1731. .unwrap(),
  1732. vec![&mut account_account, &mut owner2_account],
  1733. )
  1734. .unwrap();
  1735. // wrong owner
  1736. assert_eq!(
  1737. Err(TokenError::OwnerMismatch.into()),
  1738. do_process_instruction(
  1739. set_authority(
  1740. &program_id,
  1741. &mint_key,
  1742. Some(&owner3_key),
  1743. AuthorityType::MintTokens,
  1744. &owner2_key,
  1745. &[]
  1746. )
  1747. .unwrap(),
  1748. vec![&mut mint_account, &mut owner2_account],
  1749. )
  1750. );
  1751. // owner did not sign
  1752. let mut instruction = set_authority(
  1753. &program_id,
  1754. &mint_key,
  1755. Some(&owner2_key),
  1756. AuthorityType::MintTokens,
  1757. &owner_key,
  1758. &[],
  1759. )
  1760. .unwrap();
  1761. instruction.accounts[1].is_signer = false;
  1762. assert_eq!(
  1763. Err(ProgramError::MissingRequiredSignature),
  1764. do_process_instruction(instruction, vec![&mut mint_account, &mut owner_account],)
  1765. );
  1766. // cannot freeze
  1767. assert_eq!(
  1768. Err(TokenError::MintCannotFreeze.into()),
  1769. do_process_instruction(
  1770. set_authority(
  1771. &program_id,
  1772. &mint_key,
  1773. Some(&owner2_key),
  1774. AuthorityType::FreezeAccount,
  1775. &owner_key,
  1776. &[],
  1777. )
  1778. .unwrap(),
  1779. vec![&mut mint_account, &mut owner_account],
  1780. )
  1781. );
  1782. // set owner
  1783. do_process_instruction(
  1784. set_authority(
  1785. &program_id,
  1786. &mint_key,
  1787. Some(&owner2_key),
  1788. AuthorityType::MintTokens,
  1789. &owner_key,
  1790. &[],
  1791. )
  1792. .unwrap(),
  1793. vec![&mut mint_account, &mut owner_account],
  1794. )
  1795. .unwrap();
  1796. // set owner to None
  1797. do_process_instruction(
  1798. set_authority(
  1799. &program_id,
  1800. &mint_key,
  1801. None,
  1802. AuthorityType::MintTokens,
  1803. &owner2_key,
  1804. &[],
  1805. )
  1806. .unwrap(),
  1807. vec![&mut mint_account, &mut owner2_account],
  1808. )
  1809. .unwrap();
  1810. // test unsetting mint_authority is one-way operation
  1811. assert_eq!(
  1812. Err(TokenError::FixedSupply.into()),
  1813. do_process_instruction(
  1814. set_authority(
  1815. &program_id,
  1816. &mint2_key,
  1817. Some(&owner2_key),
  1818. AuthorityType::MintTokens,
  1819. &owner_key,
  1820. &[]
  1821. )
  1822. .unwrap(),
  1823. vec![&mut mint_account, &mut owner_account],
  1824. )
  1825. );
  1826. // set freeze_authority
  1827. do_process_instruction(
  1828. set_authority(
  1829. &program_id,
  1830. &mint2_key,
  1831. Some(&owner2_key),
  1832. AuthorityType::FreezeAccount,
  1833. &owner_key,
  1834. &[],
  1835. )
  1836. .unwrap(),
  1837. vec![&mut mint2_account, &mut owner_account],
  1838. )
  1839. .unwrap();
  1840. // test unsetting freeze_authority is one-way operation
  1841. do_process_instruction(
  1842. set_authority(
  1843. &program_id,
  1844. &mint2_key,
  1845. None,
  1846. AuthorityType::FreezeAccount,
  1847. &owner2_key,
  1848. &[],
  1849. )
  1850. .unwrap(),
  1851. vec![&mut mint2_account, &mut owner2_account],
  1852. )
  1853. .unwrap();
  1854. assert_eq!(
  1855. Err(TokenError::MintCannotFreeze.into()),
  1856. do_process_instruction(
  1857. set_authority(
  1858. &program_id,
  1859. &mint2_key,
  1860. Some(&owner2_key),
  1861. AuthorityType::FreezeAccount,
  1862. &owner_key,
  1863. &[],
  1864. )
  1865. .unwrap(),
  1866. vec![&mut mint2_account, &mut owner2_account],
  1867. )
  1868. );
  1869. }
  1870. #[test]
  1871. fn test_mint_to() {
  1872. let program_id = pubkey_rand();
  1873. let account_key = pubkey_rand();
  1874. let mut account_account =
  1875. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1876. let account2_key = pubkey_rand();
  1877. let mut account2_account =
  1878. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1879. let account3_key = pubkey_rand();
  1880. let mut account3_account =
  1881. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1882. let mismatch_key = pubkey_rand();
  1883. let mut mismatch_account =
  1884. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1885. let owner_key = pubkey_rand();
  1886. let mut owner_account = SolanaAccount::default();
  1887. let owner2_key = pubkey_rand();
  1888. let mut owner2_account = SolanaAccount::default();
  1889. let mint_key = pubkey_rand();
  1890. let mut mint_account =
  1891. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  1892. let mint2_key = pubkey_rand();
  1893. let uninitialized_key = pubkey_rand();
  1894. let mut uninitialized_account =
  1895. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  1896. let mut rent_sysvar = rent_sysvar();
  1897. // create new mint with owner
  1898. do_process_instruction(
  1899. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  1900. vec![&mut mint_account, &mut rent_sysvar],
  1901. )
  1902. .unwrap();
  1903. // create account
  1904. do_process_instruction(
  1905. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  1906. vec![
  1907. &mut account_account,
  1908. &mut mint_account,
  1909. &mut owner_account,
  1910. &mut rent_sysvar,
  1911. ],
  1912. )
  1913. .unwrap();
  1914. // create another account
  1915. do_process_instruction(
  1916. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  1917. vec![
  1918. &mut account2_account,
  1919. &mut mint_account,
  1920. &mut owner_account,
  1921. &mut rent_sysvar,
  1922. ],
  1923. )
  1924. .unwrap();
  1925. // create another account
  1926. do_process_instruction(
  1927. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  1928. vec![
  1929. &mut account3_account,
  1930. &mut mint_account,
  1931. &mut owner_account,
  1932. &mut rent_sysvar,
  1933. ],
  1934. )
  1935. .unwrap();
  1936. // create mismatch account
  1937. do_process_instruction(
  1938. initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
  1939. vec![
  1940. &mut mismatch_account,
  1941. &mut mint_account,
  1942. &mut owner_account,
  1943. &mut rent_sysvar,
  1944. ],
  1945. )
  1946. .unwrap();
  1947. let account: &mut Account = state::unpack(&mut mismatch_account.data).unwrap();
  1948. account.mint = mint2_key;
  1949. // mint to
  1950. do_process_instruction(
  1951. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
  1952. vec![&mut mint_account, &mut account_account, &mut owner_account],
  1953. )
  1954. .unwrap();
  1955. let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  1956. assert_eq!(mint.supply, 42);
  1957. let dest_account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  1958. assert_eq!(dest_account.amount, 42);
  1959. // mint to another account to test supply accumulation
  1960. do_process_instruction(
  1961. mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
  1962. vec![&mut mint_account, &mut account2_account, &mut owner_account],
  1963. )
  1964. .unwrap();
  1965. let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  1966. assert_eq!(mint.supply, 84);
  1967. let dest_account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
  1968. assert_eq!(dest_account.amount, 42);
  1969. // missing signer
  1970. let mut instruction =
  1971. mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap();
  1972. instruction.accounts[2].is_signer = false;
  1973. assert_eq!(
  1974. Err(ProgramError::MissingRequiredSignature),
  1975. do_process_instruction(
  1976. instruction,
  1977. vec![&mut mint_account, &mut account2_account, &mut owner_account],
  1978. )
  1979. );
  1980. // mismatch account
  1981. assert_eq!(
  1982. Err(TokenError::MintMismatch.into()),
  1983. do_process_instruction(
  1984. mint_to(&program_id, &mint_key, &mismatch_key, &owner_key, &[], 42).unwrap(),
  1985. vec![&mut mint_account, &mut mismatch_account, &mut owner_account],
  1986. )
  1987. );
  1988. // missing owner
  1989. assert_eq!(
  1990. Err(TokenError::OwnerMismatch.into()),
  1991. do_process_instruction(
  1992. mint_to(&program_id, &mint_key, &account2_key, &owner2_key, &[], 42).unwrap(),
  1993. vec![
  1994. &mut mint_account,
  1995. &mut account2_account,
  1996. &mut owner2_account,
  1997. ],
  1998. )
  1999. );
  2000. // uninitialized destination account
  2001. assert_eq!(
  2002. Err(TokenError::UninitializedState.into()),
  2003. do_process_instruction(
  2004. mint_to(
  2005. &program_id,
  2006. &mint_key,
  2007. &uninitialized_key,
  2008. &owner_key,
  2009. &[],
  2010. 42
  2011. )
  2012. .unwrap(),
  2013. vec![
  2014. &mut mint_account,
  2015. &mut uninitialized_account,
  2016. &mut owner_account,
  2017. ],
  2018. )
  2019. );
  2020. // unset mint_authority and test minting fails
  2021. do_process_instruction(
  2022. set_authority(
  2023. &program_id,
  2024. &mint_key,
  2025. None,
  2026. AuthorityType::MintTokens,
  2027. &owner_key,
  2028. &[],
  2029. )
  2030. .unwrap(),
  2031. vec![&mut mint_account, &mut owner_account],
  2032. )
  2033. .unwrap();
  2034. assert_eq!(
  2035. Err(TokenError::FixedSupply.into()),
  2036. do_process_instruction(
  2037. mint_to(&program_id, &mint_key, &account2_key, &owner_key, &[], 42).unwrap(),
  2038. vec![&mut mint_account, &mut account2_account, &mut owner_account],
  2039. )
  2040. );
  2041. }
  2042. #[test]
  2043. fn test_burn() {
  2044. let program_id = pubkey_rand();
  2045. let account_key = pubkey_rand();
  2046. let mut account_account =
  2047. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2048. let account2_key = pubkey_rand();
  2049. let mut account2_account =
  2050. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2051. let account3_key = pubkey_rand();
  2052. let mut account3_account =
  2053. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2054. let delegate_key = pubkey_rand();
  2055. let mut delegate_account = SolanaAccount::default();
  2056. let mismatch_key = pubkey_rand();
  2057. let mut mismatch_account =
  2058. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2059. let owner_key = pubkey_rand();
  2060. let mut owner_account = SolanaAccount::default();
  2061. let owner2_key = pubkey_rand();
  2062. let mut owner2_account = SolanaAccount::default();
  2063. let mint_key = pubkey_rand();
  2064. let mut mint_account =
  2065. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  2066. let mint2_key = pubkey_rand();
  2067. let mut rent_sysvar = rent_sysvar();
  2068. // create new mint
  2069. do_process_instruction(
  2070. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  2071. vec![&mut mint_account, &mut rent_sysvar],
  2072. )
  2073. .unwrap();
  2074. // create account
  2075. do_process_instruction(
  2076. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  2077. vec![
  2078. &mut account_account,
  2079. &mut mint_account,
  2080. &mut owner_account,
  2081. &mut rent_sysvar,
  2082. ],
  2083. )
  2084. .unwrap();
  2085. // create another account
  2086. do_process_instruction(
  2087. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  2088. vec![
  2089. &mut account2_account,
  2090. &mut mint_account,
  2091. &mut owner_account,
  2092. &mut rent_sysvar,
  2093. ],
  2094. )
  2095. .unwrap();
  2096. // create another account
  2097. do_process_instruction(
  2098. initialize_account(&program_id, &account3_key, &mint_key, &owner_key).unwrap(),
  2099. vec![
  2100. &mut account3_account,
  2101. &mut mint_account,
  2102. &mut owner_account,
  2103. &mut rent_sysvar,
  2104. ],
  2105. )
  2106. .unwrap();
  2107. // create mismatch account
  2108. do_process_instruction(
  2109. initialize_account(&program_id, &mismatch_key, &mint_key, &owner_key).unwrap(),
  2110. vec![
  2111. &mut mismatch_account,
  2112. &mut mint_account,
  2113. &mut owner_account,
  2114. &mut rent_sysvar,
  2115. ],
  2116. )
  2117. .unwrap();
  2118. let account: &mut Account = state::unpack(&mut mismatch_account.data).unwrap();
  2119. account.mint = mint2_key;
  2120. // mint to account
  2121. do_process_instruction(
  2122. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  2123. vec![&mut mint_account, &mut account_account, &mut owner_account],
  2124. )
  2125. .unwrap();
  2126. // missing signer
  2127. let mut instruction =
  2128. burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 42).unwrap();
  2129. instruction.accounts[1].is_signer = false;
  2130. assert_eq!(
  2131. Err(TokenError::OwnerMismatch.into()),
  2132. do_process_instruction(
  2133. instruction,
  2134. vec![
  2135. &mut account_account,
  2136. &mut mint_account,
  2137. &mut delegate_account
  2138. ],
  2139. )
  2140. );
  2141. // missing owner
  2142. assert_eq!(
  2143. Err(TokenError::OwnerMismatch.into()),
  2144. do_process_instruction(
  2145. burn(&program_id, &account_key, &mint_key, &owner2_key, &[], 42).unwrap(),
  2146. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  2147. )
  2148. );
  2149. // mint mismatch
  2150. assert_eq!(
  2151. Err(TokenError::MintMismatch.into()),
  2152. do_process_instruction(
  2153. burn(&program_id, &mismatch_key, &mint_key, &owner_key, &[], 42).unwrap(),
  2154. vec![&mut mismatch_account, &mut mint_account, &mut owner_account],
  2155. )
  2156. );
  2157. // burn
  2158. do_process_instruction(
  2159. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 21).unwrap(),
  2160. vec![&mut account_account, &mut mint_account, &mut owner_account],
  2161. )
  2162. .unwrap();
  2163. // burn2, with incorrect decimals
  2164. assert_eq!(
  2165. Err(TokenError::MintDecimalsMismatch.into()),
  2166. do_process_instruction(
  2167. burn2(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 3).unwrap(),
  2168. vec![&mut account_account, &mut mint_account, &mut owner_account],
  2169. )
  2170. );
  2171. // burn2
  2172. do_process_instruction(
  2173. burn2(&program_id, &account_key, &mint_key, &owner_key, &[], 21, 2).unwrap(),
  2174. vec![&mut account_account, &mut mint_account, &mut owner_account],
  2175. )
  2176. .unwrap();
  2177. let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  2178. assert_eq!(mint.supply, 1000 - 42);
  2179. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  2180. assert_eq!(account.amount, 1000 - 42);
  2181. // insufficient funds
  2182. assert_eq!(
  2183. Err(TokenError::InsufficientFunds.into()),
  2184. do_process_instruction(
  2185. burn(
  2186. &program_id,
  2187. &account_key,
  2188. &mint_key,
  2189. &owner_key,
  2190. &[],
  2191. 100_000_000
  2192. )
  2193. .unwrap(),
  2194. vec![&mut account_account, &mut mint_account, &mut owner_account],
  2195. )
  2196. );
  2197. // approve delegate
  2198. do_process_instruction(
  2199. approve(
  2200. &program_id,
  2201. &account_key,
  2202. &delegate_key,
  2203. &owner_key,
  2204. &[],
  2205. 84,
  2206. )
  2207. .unwrap(),
  2208. vec![
  2209. &mut account_account,
  2210. &mut delegate_account,
  2211. &mut owner_account,
  2212. ],
  2213. )
  2214. .unwrap();
  2215. // not a delegate of source account
  2216. assert_eq!(
  2217. Err(TokenError::InsufficientFunds.into()),
  2218. do_process_instruction(
  2219. burn(
  2220. &program_id,
  2221. &account_key,
  2222. &mint_key,
  2223. &owner_key,
  2224. &[],
  2225. 100_000_000
  2226. )
  2227. .unwrap(),
  2228. vec![&mut account_account, &mut mint_account, &mut owner_account],
  2229. )
  2230. );
  2231. // burn via delegate
  2232. do_process_instruction(
  2233. burn(&program_id, &account_key, &mint_key, &delegate_key, &[], 84).unwrap(),
  2234. vec![
  2235. &mut account_account,
  2236. &mut mint_account,
  2237. &mut delegate_account,
  2238. ],
  2239. )
  2240. .unwrap();
  2241. // match
  2242. let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  2243. assert_eq!(mint.supply, 1000 - 42 - 84);
  2244. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  2245. assert_eq!(account.amount, 1000 - 42 - 84);
  2246. // insufficient funds approved via delegate
  2247. assert_eq!(
  2248. Err(TokenError::OwnerMismatch.into()),
  2249. do_process_instruction(
  2250. burn(
  2251. &program_id,
  2252. &account_key,
  2253. &mint_key,
  2254. &delegate_key,
  2255. &[],
  2256. 100
  2257. )
  2258. .unwrap(),
  2259. vec![
  2260. &mut account_account,
  2261. &mut mint_account,
  2262. &mut delegate_account
  2263. ],
  2264. )
  2265. );
  2266. }
  2267. #[test]
  2268. fn test_multisig() {
  2269. let program_id = pubkey_rand();
  2270. let mint_key = pubkey_rand();
  2271. let mut mint_account =
  2272. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  2273. let account_key = pubkey_rand();
  2274. let mut account =
  2275. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2276. let account2_key = pubkey_rand();
  2277. let mut account2_account =
  2278. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2279. let owner_key = pubkey_rand();
  2280. let mut owner_account = SolanaAccount::default();
  2281. let multisig_key = pubkey_rand();
  2282. let mut multisig_account = SolanaAccount::new(42, size_of::<Multisig>(), &program_id);
  2283. let multisig_delegate_key = pubkey_rand();
  2284. let mut multisig_delegate_account = SolanaAccount::new(
  2285. multisig_minimum_balance(),
  2286. size_of::<Multisig>(),
  2287. &program_id,
  2288. );
  2289. let signer_keys = vec![pubkey_rand(); MAX_SIGNERS];
  2290. let signer_key_refs: Vec<&Pubkey> = signer_keys.iter().map(|key| key).collect();
  2291. let mut signer_accounts = vec![SolanaAccount::new(0, 0, &program_id); MAX_SIGNERS];
  2292. let mut rent_sysvar = rent_sysvar();
  2293. // multisig is not rent exempt
  2294. let account_info_iter = &mut signer_accounts.iter_mut();
  2295. assert_eq!(
  2296. Err(TokenError::NotRentExempt.into()),
  2297. do_process_instruction(
  2298. initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
  2299. vec![
  2300. &mut multisig_account,
  2301. &mut rent_sysvar,
  2302. &mut account_info_iter.next().unwrap(),
  2303. ],
  2304. )
  2305. );
  2306. multisig_account.lamports = multisig_minimum_balance();
  2307. // single signer
  2308. let account_info_iter = &mut signer_accounts.iter_mut();
  2309. do_process_instruction(
  2310. initialize_multisig(&program_id, &multisig_key, &[&signer_keys[0]], 1).unwrap(),
  2311. vec![
  2312. &mut multisig_account,
  2313. &mut rent_sysvar,
  2314. &mut account_info_iter.next().unwrap(),
  2315. ],
  2316. )
  2317. .unwrap();
  2318. // multiple signer
  2319. let account_info_iter = &mut signer_accounts.iter_mut();
  2320. do_process_instruction(
  2321. initialize_multisig(
  2322. &program_id,
  2323. &multisig_delegate_key,
  2324. &signer_key_refs,
  2325. MAX_SIGNERS as u8,
  2326. )
  2327. .unwrap(),
  2328. vec![
  2329. &mut multisig_delegate_account,
  2330. &mut rent_sysvar,
  2331. &mut account_info_iter.next().unwrap(),
  2332. &mut account_info_iter.next().unwrap(),
  2333. &mut account_info_iter.next().unwrap(),
  2334. &mut account_info_iter.next().unwrap(),
  2335. &mut account_info_iter.next().unwrap(),
  2336. &mut account_info_iter.next().unwrap(),
  2337. &mut account_info_iter.next().unwrap(),
  2338. &mut account_info_iter.next().unwrap(),
  2339. &mut account_info_iter.next().unwrap(),
  2340. &mut account_info_iter.next().unwrap(),
  2341. &mut account_info_iter.next().unwrap(),
  2342. ],
  2343. )
  2344. .unwrap();
  2345. // create new mint with multisig owner
  2346. do_process_instruction(
  2347. initialize_mint(&program_id, &mint_key, &multisig_key, None, 2).unwrap(),
  2348. vec![&mut mint_account, &mut rent_sysvar],
  2349. )
  2350. .unwrap();
  2351. // create account with multisig owner
  2352. do_process_instruction(
  2353. initialize_account(&program_id, &account_key, &mint_key, &multisig_key).unwrap(),
  2354. vec![
  2355. &mut account,
  2356. &mut mint_account,
  2357. &mut multisig_account,
  2358. &mut rent_sysvar,
  2359. ],
  2360. )
  2361. .unwrap();
  2362. // create another account with multisig owner
  2363. do_process_instruction(
  2364. initialize_account(
  2365. &program_id,
  2366. &account2_key,
  2367. &mint_key,
  2368. &multisig_delegate_key,
  2369. )
  2370. .unwrap(),
  2371. vec![
  2372. &mut account2_account,
  2373. &mut mint_account,
  2374. &mut multisig_account,
  2375. &mut rent_sysvar,
  2376. ],
  2377. )
  2378. .unwrap();
  2379. // mint to account
  2380. let account_info_iter = &mut signer_accounts.iter_mut();
  2381. do_process_instruction(
  2382. mint_to(
  2383. &program_id,
  2384. &mint_key,
  2385. &account_key,
  2386. &multisig_key,
  2387. &[&signer_keys[0]],
  2388. 1000,
  2389. )
  2390. .unwrap(),
  2391. vec![
  2392. &mut mint_account,
  2393. &mut account,
  2394. &mut multisig_account,
  2395. &mut account_info_iter.next().unwrap(),
  2396. ],
  2397. )
  2398. .unwrap();
  2399. // approve
  2400. let account_info_iter = &mut signer_accounts.iter_mut();
  2401. do_process_instruction(
  2402. approve(
  2403. &program_id,
  2404. &account_key,
  2405. &multisig_delegate_key,
  2406. &multisig_key,
  2407. &[&signer_keys[0]],
  2408. 100,
  2409. )
  2410. .unwrap(),
  2411. vec![
  2412. &mut account,
  2413. &mut multisig_delegate_account,
  2414. &mut multisig_account,
  2415. &mut account_info_iter.next().unwrap(),
  2416. ],
  2417. )
  2418. .unwrap();
  2419. // transfer
  2420. let account_info_iter = &mut signer_accounts.iter_mut();
  2421. do_process_instruction(
  2422. transfer(
  2423. &program_id,
  2424. &account_key,
  2425. &account2_key,
  2426. &multisig_key,
  2427. &[&signer_keys[0]],
  2428. 42,
  2429. )
  2430. .unwrap(),
  2431. vec![
  2432. &mut account,
  2433. &mut account2_account,
  2434. &mut multisig_account,
  2435. &mut account_info_iter.next().unwrap(),
  2436. ],
  2437. )
  2438. .unwrap();
  2439. // transfer via delegate
  2440. let account_info_iter = &mut signer_accounts.iter_mut();
  2441. do_process_instruction(
  2442. transfer(
  2443. &program_id,
  2444. &account_key,
  2445. &account2_key,
  2446. &multisig_delegate_key,
  2447. &signer_key_refs,
  2448. 42,
  2449. )
  2450. .unwrap(),
  2451. vec![
  2452. &mut account,
  2453. &mut account2_account,
  2454. &mut multisig_delegate_account,
  2455. &mut account_info_iter.next().unwrap(),
  2456. &mut account_info_iter.next().unwrap(),
  2457. &mut account_info_iter.next().unwrap(),
  2458. &mut account_info_iter.next().unwrap(),
  2459. &mut account_info_iter.next().unwrap(),
  2460. &mut account_info_iter.next().unwrap(),
  2461. &mut account_info_iter.next().unwrap(),
  2462. &mut account_info_iter.next().unwrap(),
  2463. &mut account_info_iter.next().unwrap(),
  2464. &mut account_info_iter.next().unwrap(),
  2465. &mut account_info_iter.next().unwrap(),
  2466. ],
  2467. )
  2468. .unwrap();
  2469. // mint to
  2470. let account_info_iter = &mut signer_accounts.iter_mut();
  2471. do_process_instruction(
  2472. mint_to(
  2473. &program_id,
  2474. &mint_key,
  2475. &account2_key,
  2476. &multisig_key,
  2477. &[&signer_keys[0]],
  2478. 42,
  2479. )
  2480. .unwrap(),
  2481. vec![
  2482. &mut mint_account,
  2483. &mut account2_account,
  2484. &mut multisig_account,
  2485. &mut account_info_iter.next().unwrap(),
  2486. ],
  2487. )
  2488. .unwrap();
  2489. // burn
  2490. let account_info_iter = &mut signer_accounts.iter_mut();
  2491. do_process_instruction(
  2492. burn(
  2493. &program_id,
  2494. &account_key,
  2495. &mint_key,
  2496. &multisig_key,
  2497. &[&signer_keys[0]],
  2498. 42,
  2499. )
  2500. .unwrap(),
  2501. vec![
  2502. &mut account,
  2503. &mut mint_account,
  2504. &mut multisig_account,
  2505. &mut account_info_iter.next().unwrap(),
  2506. ],
  2507. )
  2508. .unwrap();
  2509. // burn via delegate
  2510. let account_info_iter = &mut signer_accounts.iter_mut();
  2511. do_process_instruction(
  2512. burn(
  2513. &program_id,
  2514. &account_key,
  2515. &mint_key,
  2516. &multisig_delegate_key,
  2517. &signer_key_refs,
  2518. 42,
  2519. )
  2520. .unwrap(),
  2521. vec![
  2522. &mut account,
  2523. &mut mint_account,
  2524. &mut multisig_delegate_account,
  2525. &mut account_info_iter.next().unwrap(),
  2526. &mut account_info_iter.next().unwrap(),
  2527. &mut account_info_iter.next().unwrap(),
  2528. &mut account_info_iter.next().unwrap(),
  2529. &mut account_info_iter.next().unwrap(),
  2530. &mut account_info_iter.next().unwrap(),
  2531. &mut account_info_iter.next().unwrap(),
  2532. &mut account_info_iter.next().unwrap(),
  2533. &mut account_info_iter.next().unwrap(),
  2534. &mut account_info_iter.next().unwrap(),
  2535. &mut account_info_iter.next().unwrap(),
  2536. ],
  2537. )
  2538. .unwrap();
  2539. // freeze account
  2540. let account3_key = pubkey_rand();
  2541. let mut account3_account =
  2542. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2543. let mint2_key = pubkey_rand();
  2544. let mut mint2_account =
  2545. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  2546. do_process_instruction(
  2547. initialize_mint(
  2548. &program_id,
  2549. &mint2_key,
  2550. &multisig_key,
  2551. Some(&multisig_key),
  2552. 2,
  2553. )
  2554. .unwrap(),
  2555. vec![&mut mint2_account, &mut rent_sysvar],
  2556. )
  2557. .unwrap();
  2558. do_process_instruction(
  2559. initialize_account(&program_id, &account3_key, &mint2_key, &owner_key).unwrap(),
  2560. vec![
  2561. &mut account3_account,
  2562. &mut mint2_account,
  2563. &mut owner_account,
  2564. &mut rent_sysvar,
  2565. ],
  2566. )
  2567. .unwrap();
  2568. let account_info_iter = &mut signer_accounts.iter_mut();
  2569. do_process_instruction(
  2570. mint_to(
  2571. &program_id,
  2572. &mint2_key,
  2573. &account3_key,
  2574. &multisig_key,
  2575. &[&signer_keys[0]],
  2576. 1000,
  2577. )
  2578. .unwrap(),
  2579. vec![
  2580. &mut mint2_account,
  2581. &mut account3_account,
  2582. &mut multisig_account,
  2583. &mut account_info_iter.next().unwrap(),
  2584. ],
  2585. )
  2586. .unwrap();
  2587. let account_info_iter = &mut signer_accounts.iter_mut();
  2588. do_process_instruction(
  2589. freeze_account(
  2590. &program_id,
  2591. &account3_key,
  2592. &mint2_key,
  2593. &multisig_key,
  2594. &[&signer_keys[0]],
  2595. )
  2596. .unwrap(),
  2597. vec![
  2598. &mut account3_account,
  2599. &mut mint2_account,
  2600. &mut multisig_account,
  2601. &mut account_info_iter.next().unwrap(),
  2602. ],
  2603. )
  2604. .unwrap();
  2605. // do SetAuthority on mint
  2606. let account_info_iter = &mut signer_accounts.iter_mut();
  2607. do_process_instruction(
  2608. set_authority(
  2609. &program_id,
  2610. &mint_key,
  2611. Some(&owner_key),
  2612. AuthorityType::MintTokens,
  2613. &multisig_key,
  2614. &[&signer_keys[0]],
  2615. )
  2616. .unwrap(),
  2617. vec![
  2618. &mut mint_account,
  2619. &mut multisig_account,
  2620. &mut account_info_iter.next().unwrap(),
  2621. ],
  2622. )
  2623. .unwrap();
  2624. // do SetAuthority on account
  2625. let account_info_iter = &mut signer_accounts.iter_mut();
  2626. do_process_instruction(
  2627. set_authority(
  2628. &program_id,
  2629. &account_key,
  2630. Some(&owner_key),
  2631. AuthorityType::AccountHolder,
  2632. &multisig_key,
  2633. &[&signer_keys[0]],
  2634. )
  2635. .unwrap(),
  2636. vec![
  2637. &mut account,
  2638. &mut multisig_account,
  2639. &mut account_info_iter.next().unwrap(),
  2640. ],
  2641. )
  2642. .unwrap();
  2643. }
  2644. #[test]
  2645. fn test_validate_owner() {
  2646. let program_id = pubkey_rand();
  2647. let owner_key = pubkey_rand();
  2648. let mut signer_keys = [Pubkey::default(); MAX_SIGNERS];
  2649. for signer_key in signer_keys.iter_mut().take(MAX_SIGNERS) {
  2650. *signer_key = pubkey_rand();
  2651. }
  2652. let mut signer_lamports = 0;
  2653. let mut signer_data = vec![];
  2654. let mut signers = vec![
  2655. AccountInfo::new(
  2656. &owner_key,
  2657. true,
  2658. false,
  2659. &mut signer_lamports,
  2660. &mut signer_data,
  2661. &program_id,
  2662. false,
  2663. Epoch::default(),
  2664. );
  2665. MAX_SIGNERS + 1
  2666. ];
  2667. for (signer, key) in signers.iter_mut().zip(&signer_keys) {
  2668. signer.key = key;
  2669. }
  2670. let mut lamports = 0;
  2671. let mut data = vec![0; size_of::<Multisig>()];
  2672. let mut multisig: &mut Multisig = state::unpack_unchecked(&mut data).unwrap();
  2673. multisig.m = MAX_SIGNERS as u8;
  2674. multisig.n = MAX_SIGNERS as u8;
  2675. multisig.signers = signer_keys;
  2676. multisig.is_initialized = true;
  2677. let owner_account_info = AccountInfo::new(
  2678. &owner_key,
  2679. false,
  2680. false,
  2681. &mut lamports,
  2682. &mut data,
  2683. &program_id,
  2684. false,
  2685. Epoch::default(),
  2686. );
  2687. // full 11 of 11
  2688. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
  2689. // 1 of 11
  2690. {
  2691. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2692. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2693. multisig.m = 1;
  2694. }
  2695. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
  2696. // 2:1
  2697. {
  2698. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2699. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2700. multisig.m = 2;
  2701. multisig.n = 1;
  2702. }
  2703. assert_eq!(
  2704. Err(ProgramError::MissingRequiredSignature),
  2705. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
  2706. );
  2707. // 0:11
  2708. {
  2709. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2710. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2711. multisig.m = 0;
  2712. multisig.n = 11;
  2713. }
  2714. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers).unwrap();
  2715. // 2:11 but 0 provided
  2716. {
  2717. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2718. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2719. multisig.m = 2;
  2720. multisig.n = 11;
  2721. }
  2722. assert_eq!(
  2723. Err(ProgramError::MissingRequiredSignature),
  2724. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &[])
  2725. );
  2726. // 2:11 but 1 provided
  2727. {
  2728. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2729. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2730. multisig.m = 2;
  2731. multisig.n = 11;
  2732. }
  2733. assert_eq!(
  2734. Err(ProgramError::MissingRequiredSignature),
  2735. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[0..1])
  2736. );
  2737. // 2:11, 2 from middle provided
  2738. {
  2739. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2740. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2741. multisig.m = 2;
  2742. multisig.n = 11;
  2743. }
  2744. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers[5..7])
  2745. .unwrap();
  2746. // 11:11, one is not a signer
  2747. {
  2748. let mut data_ref_mut = owner_account_info.data.borrow_mut();
  2749. let mut multisig: &mut Multisig = state::unpack(&mut data_ref_mut).unwrap();
  2750. multisig.m = 2;
  2751. multisig.n = 11;
  2752. }
  2753. signers[5].is_signer = false;
  2754. assert_eq!(
  2755. Err(ProgramError::MissingRequiredSignature),
  2756. Processor::validate_owner(&program_id, &owner_key, &owner_account_info, &signers)
  2757. );
  2758. signers[5].is_signer = true;
  2759. }
  2760. #[test]
  2761. fn test_close_account() {
  2762. let program_id = pubkey_rand();
  2763. let mint_key = pubkey_rand();
  2764. let mut mint_account =
  2765. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  2766. let account_key = pubkey_rand();
  2767. let mut account_account =
  2768. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2769. let account2_key = pubkey_rand();
  2770. let mut account2_account = SolanaAccount::new(
  2771. account_minimum_balance() + 42,
  2772. size_of::<Account>(),
  2773. &program_id,
  2774. );
  2775. let account3_key = pubkey_rand();
  2776. let mut account3_account =
  2777. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2778. let owner_key = pubkey_rand();
  2779. let mut owner_account = SolanaAccount::default();
  2780. let owner2_key = pubkey_rand();
  2781. let mut owner2_account = SolanaAccount::default();
  2782. let mut rent_sysvar = rent_sysvar();
  2783. // uninitialized
  2784. assert_eq!(
  2785. Err(TokenError::UninitializedState.into()),
  2786. do_process_instruction(
  2787. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  2788. vec![
  2789. &mut account_account,
  2790. &mut account3_account,
  2791. &mut owner2_account,
  2792. ],
  2793. )
  2794. );
  2795. // initialize and mint to non-native account
  2796. do_process_instruction(
  2797. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  2798. vec![&mut mint_account, &mut rent_sysvar],
  2799. )
  2800. .unwrap();
  2801. do_process_instruction(
  2802. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  2803. vec![
  2804. &mut account_account,
  2805. &mut mint_account,
  2806. &mut owner_account,
  2807. &mut rent_sysvar,
  2808. ],
  2809. )
  2810. .unwrap();
  2811. do_process_instruction(
  2812. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 42).unwrap(),
  2813. vec![
  2814. &mut mint_account,
  2815. &mut account_account,
  2816. &mut owner_account,
  2817. &mut rent_sysvar,
  2818. ],
  2819. )
  2820. .unwrap();
  2821. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  2822. assert_eq!(account.amount, 42);
  2823. // initialize native account
  2824. do_process_instruction(
  2825. initialize_account(
  2826. &program_id,
  2827. &account2_key,
  2828. &crate::native_mint::id(),
  2829. &owner_key,
  2830. )
  2831. .unwrap(),
  2832. vec![
  2833. &mut account2_account,
  2834. &mut mint_account,
  2835. &mut owner_account,
  2836. &mut rent_sysvar,
  2837. ],
  2838. )
  2839. .unwrap();
  2840. let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
  2841. assert!(account.is_native());
  2842. assert_eq!(account.amount, 42);
  2843. // close non-native account with balance
  2844. assert_eq!(
  2845. Err(TokenError::NonNativeHasBalance.into()),
  2846. do_process_instruction(
  2847. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  2848. vec![
  2849. &mut account_account,
  2850. &mut account3_account,
  2851. &mut owner_account,
  2852. ],
  2853. )
  2854. );
  2855. assert_eq!(account_account.lamports, account_minimum_balance());
  2856. // empty account
  2857. do_process_instruction(
  2858. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 42).unwrap(),
  2859. vec![&mut account_account, &mut mint_account, &mut owner_account],
  2860. )
  2861. .unwrap();
  2862. // wrong owner
  2863. assert_eq!(
  2864. Err(TokenError::OwnerMismatch.into()),
  2865. do_process_instruction(
  2866. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  2867. vec![
  2868. &mut account_account,
  2869. &mut account3_account,
  2870. &mut owner2_account,
  2871. ],
  2872. )
  2873. );
  2874. // close account
  2875. do_process_instruction(
  2876. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  2877. vec![
  2878. &mut account_account,
  2879. &mut account3_account,
  2880. &mut owner_account,
  2881. ],
  2882. )
  2883. .unwrap();
  2884. let account: &mut Account = state::unpack_unchecked(&mut account_account.data).unwrap();
  2885. assert_eq!(account_account.lamports, 0);
  2886. assert_eq!(account.amount, 0);
  2887. assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
  2888. // fund and initialize new non-native account to test close authority
  2889. let account_key = pubkey_rand();
  2890. let mut account_account =
  2891. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2892. let owner2_key = pubkey_rand();
  2893. let mut owner2_account =
  2894. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2895. do_process_instruction(
  2896. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  2897. vec![
  2898. &mut account_account,
  2899. &mut mint_account,
  2900. &mut owner_account,
  2901. &mut rent_sysvar,
  2902. ],
  2903. )
  2904. .unwrap();
  2905. account_account.lamports = 2;
  2906. do_process_instruction(
  2907. set_authority(
  2908. &program_id,
  2909. &account_key,
  2910. Some(&owner2_key),
  2911. AuthorityType::CloseAccount,
  2912. &owner_key,
  2913. &[],
  2914. )
  2915. .unwrap(),
  2916. vec![&mut account_account, &mut owner_account],
  2917. )
  2918. .unwrap();
  2919. // account owner cannot authorize close if close_authority is set
  2920. assert_eq!(
  2921. Err(TokenError::OwnerMismatch.into()),
  2922. do_process_instruction(
  2923. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  2924. vec![
  2925. &mut account_account,
  2926. &mut account3_account,
  2927. &mut owner_account,
  2928. ],
  2929. )
  2930. );
  2931. // close non-native account with close_authority
  2932. do_process_instruction(
  2933. close_account(&program_id, &account_key, &account3_key, &owner2_key, &[]).unwrap(),
  2934. vec![
  2935. &mut account_account,
  2936. &mut account3_account,
  2937. &mut owner2_account,
  2938. ],
  2939. )
  2940. .unwrap();
  2941. assert_eq!(account_account.lamports, 0);
  2942. assert_eq!(account.amount, 0);
  2943. assert_eq!(account3_account.lamports, 2 * account_minimum_balance() + 2);
  2944. // close native account
  2945. do_process_instruction(
  2946. close_account(&program_id, &account2_key, &account3_key, &owner_key, &[]).unwrap(),
  2947. vec![
  2948. &mut account2_account,
  2949. &mut account3_account,
  2950. &mut owner_account,
  2951. ],
  2952. )
  2953. .unwrap();
  2954. let account: &mut Account = state::unpack_unchecked(&mut account2_account.data).unwrap();
  2955. assert!(account.is_native());
  2956. assert_eq!(account_account.lamports, 0);
  2957. assert_eq!(account.amount, 0);
  2958. assert_eq!(
  2959. account3_account.lamports,
  2960. 3 * account_minimum_balance() + 2 + 42
  2961. );
  2962. }
  2963. #[test]
  2964. fn test_native_token() {
  2965. let program_id = pubkey_rand();
  2966. let mut mint_account =
  2967. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  2968. let account_key = pubkey_rand();
  2969. let mut account_account = SolanaAccount::new(
  2970. account_minimum_balance() + 40,
  2971. size_of::<Account>(),
  2972. &program_id,
  2973. );
  2974. let account2_key = pubkey_rand();
  2975. let mut account2_account =
  2976. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  2977. let account3_key = pubkey_rand();
  2978. let mut account3_account = SolanaAccount::new(account_minimum_balance(), 0, &program_id);
  2979. let owner_key = pubkey_rand();
  2980. let mut owner_account = SolanaAccount::default();
  2981. let mut rent_sysvar = rent_sysvar();
  2982. // initialize native account
  2983. do_process_instruction(
  2984. initialize_account(
  2985. &program_id,
  2986. &account_key,
  2987. &crate::native_mint::id(),
  2988. &owner_key,
  2989. )
  2990. .unwrap(),
  2991. vec![
  2992. &mut account_account,
  2993. &mut mint_account,
  2994. &mut owner_account,
  2995. &mut rent_sysvar,
  2996. ],
  2997. )
  2998. .unwrap();
  2999. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3000. assert!(account.is_native());
  3001. assert_eq!(account.amount, 40);
  3002. // initialize native account
  3003. do_process_instruction(
  3004. initialize_account(
  3005. &program_id,
  3006. &account2_key,
  3007. &crate::native_mint::id(),
  3008. &owner_key,
  3009. )
  3010. .unwrap(),
  3011. vec![
  3012. &mut account2_account,
  3013. &mut mint_account,
  3014. &mut owner_account,
  3015. &mut rent_sysvar,
  3016. ],
  3017. )
  3018. .unwrap();
  3019. let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
  3020. assert!(account.is_native());
  3021. assert_eq!(account.amount, 0);
  3022. // mint_to unsupported
  3023. assert_eq!(
  3024. Err(TokenError::NativeNotSupported.into()),
  3025. do_process_instruction(
  3026. mint_to(
  3027. &program_id,
  3028. &crate::native_mint::id(),
  3029. &account_key,
  3030. &owner_key,
  3031. &[],
  3032. 42
  3033. )
  3034. .unwrap(),
  3035. vec![&mut mint_account, &mut account_account, &mut owner_account],
  3036. )
  3037. );
  3038. // burn unsupported
  3039. let bogus_mint_key = pubkey_rand();
  3040. let mut bogus_mint_account =
  3041. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  3042. do_process_instruction(
  3043. initialize_mint(&program_id, &bogus_mint_key, &owner_key, None, 2).unwrap(),
  3044. vec![&mut bogus_mint_account, &mut rent_sysvar],
  3045. )
  3046. .unwrap();
  3047. assert_eq!(
  3048. Err(TokenError::NativeNotSupported.into()),
  3049. do_process_instruction(
  3050. burn(
  3051. &program_id,
  3052. &account_key,
  3053. &bogus_mint_key,
  3054. &owner_key,
  3055. &[],
  3056. 42
  3057. )
  3058. .unwrap(),
  3059. vec![
  3060. &mut account_account,
  3061. &mut bogus_mint_account,
  3062. &mut owner_account
  3063. ],
  3064. )
  3065. );
  3066. // ensure can't transfer below rent-exempt reserve
  3067. assert_eq!(
  3068. Err(TokenError::InsufficientFunds.into()),
  3069. do_process_instruction(
  3070. transfer(
  3071. &program_id,
  3072. &account_key,
  3073. &account2_key,
  3074. &owner_key,
  3075. &[],
  3076. 50,
  3077. )
  3078. .unwrap(),
  3079. vec![
  3080. &mut account_account,
  3081. &mut account2_account,
  3082. &mut owner_account,
  3083. ],
  3084. )
  3085. );
  3086. // transfer between native accounts
  3087. do_process_instruction(
  3088. transfer(
  3089. &program_id,
  3090. &account_key,
  3091. &account2_key,
  3092. &owner_key,
  3093. &[],
  3094. 40,
  3095. )
  3096. .unwrap(),
  3097. vec![
  3098. &mut account_account,
  3099. &mut account2_account,
  3100. &mut owner_account,
  3101. ],
  3102. )
  3103. .unwrap();
  3104. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3105. assert!(account.is_native());
  3106. assert_eq!(account_account.lamports, account_minimum_balance());
  3107. assert_eq!(account.amount, 0);
  3108. let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
  3109. assert!(account.is_native());
  3110. assert_eq!(account2_account.lamports, account_minimum_balance() + 40);
  3111. assert_eq!(account.amount, 40);
  3112. // close native account
  3113. do_process_instruction(
  3114. close_account(&program_id, &account_key, &account3_key, &owner_key, &[]).unwrap(),
  3115. vec![
  3116. &mut account_account,
  3117. &mut account3_account,
  3118. &mut owner_account,
  3119. ],
  3120. )
  3121. .unwrap();
  3122. let account: &mut Account = state::unpack_unchecked(&mut account_account.data).unwrap();
  3123. assert!(account.is_native());
  3124. assert_eq!(account_account.lamports, 0);
  3125. assert_eq!(account.amount, 0);
  3126. assert_eq!(account3_account.lamports, 2 * account_minimum_balance());
  3127. }
  3128. #[test]
  3129. fn test_overflow() {
  3130. let program_id = pubkey_rand();
  3131. let account_key = pubkey_rand();
  3132. let mut account_account =
  3133. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  3134. let account2_key = pubkey_rand();
  3135. let mut account2_account =
  3136. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  3137. let owner_key = pubkey_rand();
  3138. let mut owner_account = SolanaAccount::default();
  3139. let owner2_key = pubkey_rand();
  3140. let mut owner2_account = SolanaAccount::default();
  3141. let mint_owner_key = pubkey_rand();
  3142. let mut mint_owner_account = SolanaAccount::default();
  3143. let mint_key = pubkey_rand();
  3144. let mut mint_account =
  3145. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  3146. let mut rent_sysvar = rent_sysvar();
  3147. // create new mint with owner
  3148. do_process_instruction(
  3149. initialize_mint(&program_id, &mint_key, &mint_owner_key, None, 2).unwrap(),
  3150. vec![&mut mint_account, &mut rent_sysvar],
  3151. )
  3152. .unwrap();
  3153. // create an account
  3154. do_process_instruction(
  3155. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  3156. vec![
  3157. &mut account_account,
  3158. &mut mint_account,
  3159. &mut owner_account,
  3160. &mut rent_sysvar,
  3161. ],
  3162. )
  3163. .unwrap();
  3164. // create another account
  3165. do_process_instruction(
  3166. initialize_account(&program_id, &account2_key, &mint_key, &owner2_key).unwrap(),
  3167. vec![
  3168. &mut account2_account,
  3169. &mut mint_account,
  3170. &mut owner2_account,
  3171. &mut rent_sysvar,
  3172. ],
  3173. )
  3174. .unwrap();
  3175. // mint the max to an account
  3176. do_process_instruction(
  3177. mint_to(
  3178. &program_id,
  3179. &mint_key,
  3180. &account_key,
  3181. &mint_owner_key,
  3182. &[],
  3183. u64::MAX,
  3184. )
  3185. .unwrap(),
  3186. vec![
  3187. &mut mint_account,
  3188. &mut account_account,
  3189. &mut mint_owner_account,
  3190. ],
  3191. )
  3192. .unwrap();
  3193. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3194. assert_eq!(account.amount, u64::MAX);
  3195. // attempt to mint one more to account
  3196. assert_eq!(
  3197. Err(TokenError::Overflow.into()),
  3198. do_process_instruction(
  3199. mint_to(
  3200. &program_id,
  3201. &mint_key,
  3202. &account_key,
  3203. &mint_owner_key,
  3204. &[],
  3205. 1,
  3206. )
  3207. .unwrap(),
  3208. vec![
  3209. &mut mint_account,
  3210. &mut account_account,
  3211. &mut mint_owner_account,
  3212. ],
  3213. )
  3214. );
  3215. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3216. assert_eq!(account.amount, u64::MAX);
  3217. // atttempt to mint one more to the other account
  3218. assert_eq!(
  3219. Err(TokenError::Overflow.into()),
  3220. do_process_instruction(
  3221. mint_to(
  3222. &program_id,
  3223. &mint_key,
  3224. &account2_key,
  3225. &mint_owner_key,
  3226. &[],
  3227. 1,
  3228. )
  3229. .unwrap(),
  3230. vec![
  3231. &mut mint_account,
  3232. &mut account2_account,
  3233. &mut mint_owner_account,
  3234. ],
  3235. )
  3236. );
  3237. // burn some of the supply
  3238. do_process_instruction(
  3239. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
  3240. vec![&mut account_account, &mut mint_account, &mut owner_account],
  3241. )
  3242. .unwrap();
  3243. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3244. assert_eq!(account.amount, u64::MAX - 100);
  3245. do_process_instruction(
  3246. mint_to(
  3247. &program_id,
  3248. &mint_key,
  3249. &account_key,
  3250. &mint_owner_key,
  3251. &[],
  3252. 100,
  3253. )
  3254. .unwrap(),
  3255. vec![
  3256. &mut mint_account,
  3257. &mut account_account,
  3258. &mut mint_owner_account,
  3259. ],
  3260. )
  3261. .unwrap();
  3262. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3263. assert_eq!(account.amount, u64::MAX);
  3264. // manipulate account balance to attempt overflow transfer
  3265. let account: &mut Account = state::unpack(&mut account2_account.data).unwrap();
  3266. account.amount = 1;
  3267. assert_eq!(
  3268. Err(TokenError::Overflow.into()),
  3269. do_process_instruction(
  3270. transfer(
  3271. &program_id,
  3272. &account2_key,
  3273. &account_key,
  3274. &owner2_key,
  3275. &[],
  3276. 1,
  3277. )
  3278. .unwrap(),
  3279. vec![
  3280. &mut account2_account,
  3281. &mut account_account,
  3282. &mut owner2_account,
  3283. ],
  3284. )
  3285. );
  3286. }
  3287. #[test]
  3288. fn test_frozen() {
  3289. let program_id = pubkey_rand();
  3290. let account_key = pubkey_rand();
  3291. let mut account_account =
  3292. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  3293. let account2_key = pubkey_rand();
  3294. let mut account2_account =
  3295. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  3296. let owner_key = pubkey_rand();
  3297. let mut owner_account = SolanaAccount::default();
  3298. let mint_key = pubkey_rand();
  3299. let mut mint_account =
  3300. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  3301. let mut rent_sysvar = rent_sysvar();
  3302. // create new mint and fund first account
  3303. do_process_instruction(
  3304. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  3305. vec![&mut mint_account, &mut rent_sysvar],
  3306. )
  3307. .unwrap();
  3308. // create account
  3309. do_process_instruction(
  3310. initialize_account(&program_id, &account_key, &mint_key, &owner_key).unwrap(),
  3311. vec![
  3312. &mut account_account,
  3313. &mut mint_account,
  3314. &mut owner_account,
  3315. &mut rent_sysvar,
  3316. ],
  3317. )
  3318. .unwrap();
  3319. // create another account
  3320. do_process_instruction(
  3321. initialize_account(&program_id, &account2_key, &mint_key, &owner_key).unwrap(),
  3322. vec![
  3323. &mut account2_account,
  3324. &mut mint_account,
  3325. &mut owner_account,
  3326. &mut rent_sysvar,
  3327. ],
  3328. )
  3329. .unwrap();
  3330. // fund first account
  3331. do_process_instruction(
  3332. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  3333. vec![&mut mint_account, &mut account_account, &mut owner_account],
  3334. )
  3335. .unwrap();
  3336. // no transfer if either account is frozen
  3337. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3338. account.state = AccountState::Frozen;
  3339. assert_eq!(
  3340. Err(TokenError::AccountFrozen.into()),
  3341. do_process_instruction(
  3342. transfer(
  3343. &program_id,
  3344. &account_key,
  3345. &account2_key,
  3346. &owner_key,
  3347. &[],
  3348. 500,
  3349. )
  3350. .unwrap(),
  3351. vec![
  3352. &mut account_account,
  3353. &mut account2_account,
  3354. &mut owner_account,
  3355. ],
  3356. )
  3357. );
  3358. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3359. account.state = AccountState::Initialized;
  3360. let account2: &mut Account = state::unpack(&mut account2_account.data).unwrap();
  3361. account2.state = AccountState::Frozen;
  3362. assert_eq!(
  3363. Err(TokenError::AccountFrozen.into()),
  3364. do_process_instruction(
  3365. transfer(
  3366. &program_id,
  3367. &account_key,
  3368. &account2_key,
  3369. &owner_key,
  3370. &[],
  3371. 500,
  3372. )
  3373. .unwrap(),
  3374. vec![
  3375. &mut account_account,
  3376. &mut account2_account,
  3377. &mut owner_account,
  3378. ],
  3379. )
  3380. );
  3381. // no approve if account is frozen
  3382. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3383. account.state = AccountState::Frozen;
  3384. let delegate_key = pubkey_rand();
  3385. let mut delegate_account = SolanaAccount::default();
  3386. assert_eq!(
  3387. Err(TokenError::AccountFrozen.into()),
  3388. do_process_instruction(
  3389. approve(
  3390. &program_id,
  3391. &account_key,
  3392. &delegate_key,
  3393. &owner_key,
  3394. &[],
  3395. 100
  3396. )
  3397. .unwrap(),
  3398. vec![
  3399. &mut account_account,
  3400. &mut delegate_account,
  3401. &mut owner_account,
  3402. ],
  3403. )
  3404. );
  3405. // no revoke if account is frozen
  3406. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3407. account.delegate = COption::Some(delegate_key);
  3408. account.delegated_amount = 100;
  3409. assert_eq!(
  3410. Err(TokenError::AccountFrozen.into()),
  3411. do_process_instruction(
  3412. revoke(&program_id, &account_key, &owner_key, &[]).unwrap(),
  3413. vec![&mut account_account, &mut owner_account],
  3414. )
  3415. );
  3416. // no set authority if account is frozen
  3417. let new_owner_key = pubkey_rand();
  3418. assert_eq!(
  3419. Err(TokenError::AccountFrozen.into()),
  3420. do_process_instruction(
  3421. set_authority(
  3422. &program_id,
  3423. &account_key,
  3424. Some(&new_owner_key),
  3425. AuthorityType::AccountHolder,
  3426. &owner_key,
  3427. &[]
  3428. )
  3429. .unwrap(),
  3430. vec![&mut account_account, &mut owner_account,],
  3431. )
  3432. );
  3433. // no mint_to if destination account is frozen
  3434. assert_eq!(
  3435. Err(TokenError::AccountFrozen.into()),
  3436. do_process_instruction(
  3437. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 100).unwrap(),
  3438. vec![&mut mint_account, &mut account_account, &mut owner_account,],
  3439. )
  3440. );
  3441. // no burn if account is frozen
  3442. assert_eq!(
  3443. Err(TokenError::AccountFrozen.into()),
  3444. do_process_instruction(
  3445. burn(&program_id, &account_key, &mint_key, &owner_key, &[], 100).unwrap(),
  3446. vec![&mut account_account, &mut mint_account, &mut owner_account],
  3447. )
  3448. );
  3449. }
  3450. #[test]
  3451. fn test_freeze_account() {
  3452. let program_id = pubkey_rand();
  3453. let account_key = pubkey_rand();
  3454. let mut account_account =
  3455. SolanaAccount::new(account_minimum_balance(), size_of::<Account>(), &program_id);
  3456. let account_owner_key = pubkey_rand();
  3457. let mut account_owner_account = SolanaAccount::default();
  3458. let owner_key = pubkey_rand();
  3459. let mut owner_account = SolanaAccount::default();
  3460. let owner2_key = pubkey_rand();
  3461. let mut owner2_account = SolanaAccount::default();
  3462. let mint_key = pubkey_rand();
  3463. let mut mint_account =
  3464. SolanaAccount::new(mint_minimum_balance(), size_of::<Mint>(), &program_id);
  3465. let mut rent_sysvar = rent_sysvar();
  3466. // create new mint with owner different from account owner
  3467. do_process_instruction(
  3468. initialize_mint(&program_id, &mint_key, &owner_key, None, 2).unwrap(),
  3469. vec![&mut mint_account, &mut rent_sysvar],
  3470. )
  3471. .unwrap();
  3472. // create account
  3473. do_process_instruction(
  3474. initialize_account(&program_id, &account_key, &mint_key, &account_owner_key).unwrap(),
  3475. vec![
  3476. &mut account_account,
  3477. &mut mint_account,
  3478. &mut account_owner_account,
  3479. &mut rent_sysvar,
  3480. ],
  3481. )
  3482. .unwrap();
  3483. // mint to account
  3484. do_process_instruction(
  3485. mint_to(&program_id, &mint_key, &account_key, &owner_key, &[], 1000).unwrap(),
  3486. vec![&mut mint_account, &mut account_account, &mut owner_account],
  3487. )
  3488. .unwrap();
  3489. // mint cannot freeze
  3490. assert_eq!(
  3491. Err(TokenError::MintCannotFreeze.into()),
  3492. do_process_instruction(
  3493. freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  3494. vec![&mut account_account, &mut mint_account, &mut owner_account],
  3495. )
  3496. );
  3497. // missing freeze_authority
  3498. let mint: &mut Mint = state::unpack(&mut mint_account.data).unwrap();
  3499. mint.freeze_authority = COption::Some(owner_key);
  3500. assert_eq!(
  3501. Err(TokenError::OwnerMismatch.into()),
  3502. do_process_instruction(
  3503. freeze_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
  3504. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  3505. )
  3506. );
  3507. // check explicit thaw
  3508. assert_eq!(
  3509. Err(TokenError::InvalidState.into()),
  3510. do_process_instruction(
  3511. thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
  3512. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  3513. )
  3514. );
  3515. // freeze
  3516. do_process_instruction(
  3517. freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  3518. vec![&mut account_account, &mut mint_account, &mut owner_account],
  3519. )
  3520. .unwrap();
  3521. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3522. assert_eq!(account.state, AccountState::Frozen);
  3523. // check explicit freeze
  3524. assert_eq!(
  3525. Err(TokenError::InvalidState.into()),
  3526. do_process_instruction(
  3527. freeze_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  3528. vec![&mut account_account, &mut mint_account, &mut owner_account],
  3529. )
  3530. );
  3531. // check thaw authority
  3532. assert_eq!(
  3533. Err(TokenError::OwnerMismatch.into()),
  3534. do_process_instruction(
  3535. thaw_account(&program_id, &account_key, &mint_key, &owner2_key, &[]).unwrap(),
  3536. vec![&mut account_account, &mut mint_account, &mut owner2_account],
  3537. )
  3538. );
  3539. // thaw
  3540. do_process_instruction(
  3541. thaw_account(&program_id, &account_key, &mint_key, &owner_key, &[]).unwrap(),
  3542. vec![&mut account_account, &mut mint_account, &mut owner_account],
  3543. )
  3544. .unwrap();
  3545. let account: &mut Account = state::unpack(&mut account_account.data).unwrap();
  3546. assert_eq!(account.state, AccountState::Initialized);
  3547. }
  3548. }