package Ġorg . ke v em . e vm . ops Ċ Ċ import Ġorg . ke v em . common . Logger Ċ import Ġorg . ke v em . common . conversions . coerce Byte List To Size Ċ import Ġorg . ke v em . e vm . collections . BigInteger Index edList Ċ import Ġorg . ke v em . e vm . collections . BigInteger Index edList . Companion . empty Byte List Ċ import Ġorg . ke v em . e vm . gas . Refund Ċ import Ġorg . ke v em . e vm . model .* Ċ import Ġjava . math . BigInteger Ċ Ċ object ĠH alt Ops Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlog : ĠLogger Ġ= ĠLogger . create Logger ( H alt Ops :: class ) ĊĊĠĠĠ Ġfun Ġstop ( context : ĠExecutionContext ): ĠExecutionContext Ġ= Ġwith ( context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcaller Ġ= Ġcurrent Call Ctx . caller ĊĠĠĠĠĠĠĠ Ġval Ġrefund Ġ= Ġcurrent Call Ctx . gas Remaining Ġ* Ġcurrent Transaction . gas Price ĊĊĠĠĠĠĠĠĠ Ġval Ġnew Call Stack Ġ= Ġdrop Last Ctx AndUpdate Current Ctx ( call Stack ) Ġ{ Ġctx , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Stack Ġ= Ġctx . stack . push Word ( Word . One ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġctx . copy ( stack Ġ= Ġnew Stack , Ġcurrent Location Ġ= Ġctx . current Location Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlog . debug (" Stack Ġsize Ġbefore Ġdrop : Ġ${ call Stack . size } Ġand Ġafter : Ġ${ new Call Stack . size }") ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcontext ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. refund ( caller , Ġrefund ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. copy ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompleted Ġ= Ġnew Call Stack . isEmpty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġnew Call Stack , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Return Data Ġ= Ġempty Byte List (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgas Used Ġ= Ġgas Used Ġ+ Ġcurrent Call Ctx . gas Used , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Call Error Ġ= ĠE vm Error . None ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġdo Return ( context : ĠExecutionContext ): ĠExecutionContext Ġ= Ġwith ( context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġ( elements , Ġ_) Ġ= Ġcontext . stack . pop Words ( 2 ) ĊĠĠĠĠĠĠĠ Ġval Ġ( data Location , Ġdata Size ) Ġ= Ġelements ĊĠĠĠĠĠĠĠ Ġval Ġ( return Data , Ġnew Memory ) Ġ= Ġmemory . read ( data Location . to BigInt (), Ġdata Size . toInt ()) ĊĊĠĠĠĠĠĠĠ Ġval Ġcaller Ġ= Ġcurrent Call Ctx . caller ĊĠĠĠĠĠĠĠ Ġval Ġrefund Ġ= Ġcurrent Call Ctx . gas Remaining Ġ* Ġcurrent Transaction . gas Price ĊĊĠĠĠĠĠĠĠ Ġval Ġnew Call Stack Ġ= Ġdrop Last Ctx AndUpdate Current Ctx ( call Stack ) Ġ{ Ġctx , Ġold Ctx Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġco erce Byte List To Size ( return Data , Ġold Ctx . return Size ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Memory Ġ= Ġctx . memory . write ( old Ctx . return Location , Ġdata ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Stack Ġ= Ġctx . stack . push Word ( Word . One ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġctx . copy ( memory Ġ= Ġnew Memory , Ġstack Ġ= Ġnew Stack , Ġcurrent Location Ġ= Ġctx . current Location Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcontext ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. refund ( caller , Ġrefund ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. copy ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompleted Ġ= Ġnew Call Stack . isEmpty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġnew Call Stack , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Return Data Ġ= ĠBigInteger Index edList . from Bytes ( return Data ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgas Used Ġ= Ġgas Used Ġ+ Ġcurrent Call Ctx . gas Used , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Call Error Ġ= ĠE vm Error . None ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġinvalid ( context : ĠExecutionContext , Ġmessage : ĠString ? Ġ= Ġnull ): ĠExecutionContext Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġerror Ġ= ĠE vm Error ( ErrorCode . INVALID _ INSTR UCTION , Ġmessage Ġ?: Ġ" Invalid Ġinstruction ") ĊĠĠĠĠĠĠĠ Ġreturn Ġfail ( context , Ġerror ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġfail ( context : ĠExecutionContext , Ġerror : ĠE vm Error ): ĠExecutionContext Ġ= Ġwith ( context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . info (" fail ing Ġwith Ġ$ error ") ĊĊĠĠĠĠĠĠĠ Ġval Ġcalling Context Ġ= Ġcurrent Call Ctx . calling Context Ġ?: Ġcontext . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġcontext . call Stack . drop Last ( 1 ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġval Ġcompleted Ġ= Ġcontext . call Stack . size Ġ== Ġ 1 ĊĊĠĠĠĠĠĠĠ Ġval Ġcall Stack Ġ= Ġupdate Last Call Ctx If Present ( calling Context . call Stack ) Ġ{ Ġctx Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Stack Ġ= Ġctx . stack . push Word ( Word . Zero ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġctx . copy ( stack Ġ= Ġnew Stack , Ġcurrent Location Ġ= Ġctx . current Location Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcalling Context . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġcall Stack , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcompleted Ġ= Ġcompleted , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlast Return Data Ġ= Ġempty Byte List (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlast Call Error Ġ= Ġerror , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgas Used Ġ= Ġgas Used Ġ+ Ġcurrent Call Ctx . gas ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrevert ( context : ĠExecutionContext ): ĠExecutionContext Ġ= Ġwith ( context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġ( elements , Ġ_) Ġ= Ġcontext . stack . pop Words ( 2 ) ĊĠĠĠĠĠĠĠ Ġval Ġ( out Mem Location , Ġout Size ) Ġ= Ġelements ĊĠĠĠĠĠĠĠ Ġval Ġ( return Data , Ġnew Memory ) Ġ= Ġmemory . read ( out Mem Location . to BigInt (), Ġout Size . toInt ()) ĊĊĠĠĠĠĠĠĠ Ġval Ġold Ctx Ġ= Ġcurrent Call Ctx ĊĠĠĠĠĠĠĠ Ġval Ġcalling Context Ġ= Ġcurrent Call Ctx . calling Context Ġ?: Ġcontext . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġcontext . call Stack . drop Last ( 1 ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġval Ġcompleted Ġ= Ġcontext . call Stack . size Ġ== Ġ 1 ĊĊĠĠĠĠĠĠĠ Ġval Ġcaller Ġ= Ġcurrent Call Ctx . caller ĊĠĠĠĠĠĠĠ Ġval Ġrefund Ġ= Ġcurrent Call Ctx . gas Remaining Ġ* Ġcurrent Transaction . gas Price ĊĊĠĠĠĠĠĠĠ Ġval Ġcall Stack Ġ= Ġupdate Last Call Ctx If Present ( calling Context . call Stack ) Ġ{ Ġctx Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġco erce Byte List To Size ( return Data , Ġold Ctx . return Size ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Memory Ġ= Ġctx . memory . write ( old Ctx . return Location , Ġdata ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Stack Ġ= Ġctx . stack . push Word ( Word . Zero ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġctx . copy ( memory Ġ= Ġnew Memory , Ġstack Ġ= Ġnew Stack , Ġcurrent Location Ġ= Ġctx . current Location Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcalling Context ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. refund ( caller , Ġrefund ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. copy ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġcall Stack , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompleted Ġ= Ġcompleted , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Return Data Ġ= ĠBigInteger Index edList . from Bytes ( return Data ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgas Used Ġ= Ġgas Used Ġ+ Ġcurrent Call Ctx . gas Used , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Call Error Ġ= ĠE vm Error . None ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsu ic ide ( context : ĠExecutionContext ): ĠExecutionContext Ġ= Ġwith ( context ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġ( a , Ġ_) Ġ= Ġcontext . stack . pop Word () ĊĠĠĠĠĠĠĠ Ġval Ġsend Fund sTo Address Ġ= Ġa . to Address () ĊĊĠĠĠĠĠĠĠ Ġval Ġcaller Ġ= Ġcurrent Call Ctx . caller ĊĠĠĠĠĠĠĠ Ġval Ġrefund Ġ= Ġcurrent Call Ctx . gas Remaining Ġ* Ġcurrent Transaction . gas Price Ġ+ ĠRef und . Self Dest ruct . wei . to BigInteger () ĊĊĠĠĠĠĠĠĠ Ġval Ġnew Call Stack Ġ= Ġdrop Last Ctx AndUpdate Current Ctx ( call Stack ) Ġ{ Ġctx , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Stack Ġ= Ġctx . stack . push Word ( Word . One ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġctx . copy ( stack Ġ= Ġnew Stack , Ġcurrent Location Ġ= Ġctx . current Location Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcontract Address Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Call Ctx . contract Address Ġ?: Ġthrow ĠRuntimeException (" can 't Ġdetermine Ġcontract Ġaddress ") ĊĠĠĠĠĠĠĠ Ġval Ġcontract Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaccounts . contract At ( contract Address ) Ġ?: Ġthrow ĠRuntimeException (" can 't Ġdetermine Ġcurrent Ġcontract ") ĊĊĠĠĠĠĠĠĠ Ġval Ġnew E vm State Ġ= Ġwith ( accounts ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Dest Balance Ġ= Ġbalance Of ( send Fund sTo Address ) Ġ+ Ġbalance Of ( contract Address ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Balance ( send Fund sTo Address , Ġnew Dest Balance ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. update Balance And Contract ( contract Address , ĠBigInteger . ZERO , Ġcontract . copy ( code Ġ= Ġempty Byte List ())) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcontext ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. refund ( caller , Ġrefund ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. copy ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcompleted Ġ= Ġnew Call Stack . isEmpty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Return Data Ġ= Ġempty Byte List (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaccounts Ġ= Ġnew E vm State , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall Stack Ġ= Ġnew Call Stack , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgas Used Ġ= Ġgas Used Ġ+ Ġcurrent Call Ctx . gas Used , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Call Error Ġ= ĠE vm Error . None ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Last Call Ctx If Present ( ĊĠĠĠĠĠĠĠ Ġcall Stack : ĠList < Call Context >, ĊĠĠĠĠĠĠĠ Ġop : Ġ( ctx : ĠCall Context ) Ġ-> ĠCall Context ĊĠĠĠ Ġ): ĠList < Call Context > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġupdated Ġ= Ġcall Stack . last OrNull ()?. let Ġ{ Ġop ( it ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( updated Ġ!= Ġnull ) Ġcall Stack . drop Last ( 1 ) Ġ+ Ġupdated ĊĠĠĠĠĠĠĠ Ġelse Ġcall Stack ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġdrop Last Ctx AndUpdate Current Ctx ( ĊĠĠĠĠĠĠĠ Ġcall Stack : ĠList < Call Context >, ĊĠĠĠĠĠĠĠ Ġop : Ġ( ctx : ĠCall Context , Ġold Ctx : ĠCall Context ) Ġ-> ĠCall Context ĊĠĠĠ Ġ): ĠList < Call Context > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġold Ctx Ġ= Ġcall Stack . last () ĊĠĠĠĠĠĠĠ Ġval Ġnew Call Stack Ġ= Ġcall Stack . drop Last ( 1 ) ĊĊĠĠĠĠĠĠĠ Ġval Ġupdated Ġ= Ġnew Call Stack . last OrNull ()?. let Ġ{ Ġop ( it , Ġold Ctx ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( updated Ġ!= Ġnull ) Ġnew Call Stack . drop Last ( 1 ) Ġ+ Ġupdated ĊĠĠĠĠĠĠĠ Ġelse Ġnew Call Stack ĊĠĠĠ Ġ} Ċ }