@@ -515,6 +515,72 @@ public void suicide(DataWord obtainerAddress) {
515515 getResult ().addDeleteAccount (this .getContractAddress ());
516516 }
517517
518+ public void suicide2 (DataWord obtainerAddress ) {
519+
520+ byte [] owner = getContextAddress ();
521+ boolean isNewContract = getContractState ().isNewContract (owner );
522+ if (isNewContract ) {
523+ suicide (obtainerAddress );
524+ return ;
525+ }
526+
527+ byte [] obtainer = obtainerAddress .toTronAddress ();
528+
529+ long balance = getContractState ().getBalance (owner );
530+
531+ if (logger .isDebugEnabled ()) {
532+ logger .debug ("Transfer to: [{}] heritage: [{}]" ,
533+ Hex .toHexString (obtainer ),
534+ balance );
535+ }
536+
537+ increaseNonce ();
538+
539+ InternalTransaction internalTx = addInternalTx (null , owner , obtainer , balance , null ,
540+ "suicide" , nonce , getContractState ().getAccount (owner ).getAssetMapV2 ());
541+
542+ if (FastByteComparisons .isEqual (owner , obtainer )) {
543+ return ;
544+ }
545+
546+ if (VMConfig .allowTvmVote ()) {
547+ withdrawRewardAndCancelVote (owner , getContractState ());
548+ balance = getContractState ().getBalance (owner );
549+ if (internalTx != null && balance != internalTx .getValue ()) {
550+ internalTx .setValue (balance );
551+ }
552+ }
553+
554+ // transfer balance and trc10
555+ createAccountIfNotExist (getContractState (), obtainer );
556+ try {
557+ MUtil .transfer (getContractState (), owner , obtainer , balance );
558+ if (VMConfig .allowTvmTransferTrc10 ()) {
559+ MUtil .transferAllToken (getContractState (), owner , obtainer );
560+ }
561+ } catch (ContractValidateException e ) {
562+ if (VMConfig .allowTvmConstantinople ()) {
563+ throw new TransferException (
564+ "transfer all token or transfer all trx failed in suicide: %s" , e .getMessage ());
565+ }
566+ throw new BytecodeExecutionException ("transfer failure" );
567+ }
568+
569+ // transfer freeze
570+ if (VMConfig .allowTvmFreeze ()) {
571+ transferDelegatedResourceToInheritor (owner , obtainer , getContractState ());
572+ }
573+
574+ // transfer freezeV2
575+ if (VMConfig .allowTvmFreezeV2 ()) {
576+ long expireUnfrozenBalance =
577+ transferFrozenV2BalanceToInheritor (owner , obtainer , getContractState ());
578+ if (expireUnfrozenBalance > 0 && internalTx != null ) {
579+ internalTx .setValue (internalTx .getValue () + expireUnfrozenBalance );
580+ }
581+ }
582+ }
583+
518584 public Repository getContractState () {
519585 return this .contractState ;
520586 }
@@ -544,6 +610,11 @@ private void transferDelegatedResourceToInheritor(byte[] ownerAddr, byte[] inher
544610
545611 // transfer all kinds of frozen balance to BlackHole
546612 repo .addBalance (inheritorAddr , frozenBalanceForBandwidthOfOwner + frozenBalanceForEnergyOfOwner );
613+
614+ if (VMConfig .allowTvmSelfdestructRestriction ()) {
615+ clearOwnerFreeze (ownerCapsule );
616+ repo .updateAccount (ownerAddr , ownerCapsule );
617+ }
547618 }
548619
549620 private long transferFrozenV2BalanceToInheritor (byte [] ownerAddr , byte [] inheritorAddr , Repository repo ) {
@@ -609,6 +680,11 @@ private long transferFrozenV2BalanceToInheritor(byte[] ownerAddr, byte[] inherit
609680 return expireUnfrozenBalance ;
610681 }
611682
683+ private void clearOwnerFreeze (AccountCapsule ownerCapsule ) {
684+ ownerCapsule .setFrozenForBandwidth (0 , 0 );
685+ ownerCapsule .setFrozenForEnergy (0 , 0 );
686+ }
687+
612688 private void clearOwnerFreezeV2 (AccountCapsule ownerCapsule ) {
613689 ownerCapsule .clearFrozenV2 ();
614690 ownerCapsule .setNetUsage (0 );
@@ -666,6 +742,38 @@ public boolean canSuicide() {
666742// return freezeCheck && voteCheck;
667743 }
668744
745+ public boolean canSuicide2 () {
746+ byte [] owner = getContextAddress ();
747+ AccountCapsule accountCapsule = getContractState ().getAccount (owner );
748+
749+ return freezeV1Check (accountCapsule ) && freezeV2Check (accountCapsule );
750+ }
751+
752+ private boolean freezeV1Check (AccountCapsule accountCapsule ) {
753+ if (!VMConfig .allowTvmFreeze ()) {
754+ return true ;
755+ }
756+
757+ // check freeze
758+ long now = getContractState ().getDynamicPropertiesStore ().getLatestBlockHeaderTimestamp ();
759+ // bandwidth
760+ if (accountCapsule .getFrozenCount () > 0
761+ && accountCapsule .getFrozenList ().stream ()
762+ .anyMatch (frozen -> frozen .getExpireTime () > now )) {
763+ return false ;
764+ }
765+ // energy
766+ Protocol .Account .Frozen frozenEnergy =
767+ accountCapsule .getAccountResource ().getFrozenBalanceForEnergy ();
768+ if (frozenEnergy .getFrozenBalance () > 0 && frozenEnergy .getExpireTime () > now ) {
769+ return false ;
770+ }
771+
772+ // check delegate
773+ return accountCapsule .getDelegatedFrozenBalanceForBandwidth () == 0
774+ && accountCapsule .getDelegatedFrozenBalanceForEnergy () == 0 ;
775+ }
776+
669777 private boolean freezeV2Check (AccountCapsule accountCapsule ) {
670778 if (!VMConfig .allowTvmFreezeV2 ()) {
671779 return true ;
0 commit comments