@@ -451,6 +451,52 @@ func TestBlockchain_AddBadBlock(t *testing.T) {
451
451
})
452
452
}
453
453
454
+ func TestBlockchain_RefundSystemFee (t * testing.T ) {
455
+ bc , acc := chain .NewSingle (t )
456
+ e := neotest .NewExecutor (t , bc , acc , acc )
457
+ neoHash := e .NativeHash (t , nativenames .Neo )
458
+
459
+ bal0 := bc .GetUtilityTokenBalance (acc .ScriptHash ())
460
+
461
+ // tx without sysfee refund
462
+ tx1 := e .NewUnsignedTx (t , neoHash , "symbol" )
463
+ e .SignTx (t , tx1 , 100000000 , acc )
464
+ vm , err := neotest .TestInvoke (bc , tx1 )
465
+ actualSysfee1 := vm .GasConsumed ()
466
+ require .NoError (t , err )
467
+
468
+ block1 := e .NewUnsignedBlock (t , tx1 )
469
+ e .SignBlock (block1 )
470
+ err = bc .AddBlock (block1 )
471
+ require .NoError (t , err )
472
+ bal1 := bc .GetUtilityTokenBalance (acc .ScriptHash ())
473
+
474
+ // tx with sysfee refund
475
+ tx2 := e .NewUnsignedTx (t , neoHash , "symbol" )
476
+ attr := transaction.Attribute {Type : transaction .RefundableSystemFeeT , Value : & transaction.RefundableSystemFee {}}
477
+ tx2 .Attributes = append (tx2 .Attributes , attr )
478
+ e .SignTx (t , tx2 , 100000000 , acc )
479
+ tx2 .NetworkFee += bc .SystemFeeRefundCost ()
480
+ vm , err = neotest .TestInvoke (bc , tx1 )
481
+ actualSysfee2 := vm .GasConsumed ()
482
+ require .NoError (t , err )
483
+ require .Equal (t , actualSysfee1 , actualSysfee2 )
484
+
485
+ block2 := e .NewUnsignedBlock (t , tx2 )
486
+ e .SignBlock (block2 )
487
+ err = bc .AddBlock (block2 )
488
+ require .NoError (t , err )
489
+ bal2 := bc .GetUtilityTokenBalance (acc .ScriptHash ())
490
+
491
+ gas1 := new (big.Int ).Sub (bal0 , bal1 )
492
+ gas2 := new (big.Int ).Sub (bal1 , bal2 )
493
+ extraNetfee := big .NewInt (int64 (io .GetVarSize (& attr )) * int64 (bc .FeePerByte ()))
494
+ extraNetfee .Add (extraNetfee , big .NewInt (bc .SystemFeeRefundCost ()))
495
+ expect := new (big.Int ).Add (gas1 , extraNetfee )
496
+ expect .Sub (expect , big .NewInt (100000000 - actualSysfee1 ))
497
+ require .Equal (t , expect , gas2 )
498
+ }
499
+
454
500
func TestBlockchain_GetHeader (t * testing.T ) {
455
501
bc , acc := chain .NewSingle (t )
456
502
e := neotest .NewExecutor (t , bc , acc , acc )
@@ -1109,14 +1155,15 @@ func TestBlockchain_VerifyTx(t *testing.T) {
1109
1155
}
1110
1156
1111
1157
testScript := []byte {byte (opcode .PUSH1 )}
1112
- newTestTx := func (t * testing.T , signer util.Uint160 , script []byte ) * transaction.Transaction {
1158
+ newTestTx := func (t * testing.T , signer util.Uint160 , script []byte , attrs ... transaction. Attribute ) * transaction.Transaction {
1113
1159
tx := transaction .New (script , 1_000_000 )
1114
1160
tx .Nonce = neotest .Nonce ()
1115
1161
tx .ValidUntilBlock = e .Chain .BlockHeight () + 5
1116
1162
tx .Signers = []transaction.Signer {{
1117
1163
Account : signer ,
1118
1164
Scopes : transaction .CalledByEntry ,
1119
1165
}}
1166
+ tx .Attributes = attrs
1120
1167
tx .NetworkFee = int64 (io .GetVarSize (tx )+ 200 /* witness */ ) * bc .FeePerByte ()
1121
1168
tx .NetworkFee += 1_000_000 // verification cost
1122
1169
return tx
@@ -1338,6 +1385,14 @@ func TestBlockchain_VerifyTx(t *testing.T) {
1338
1385
}}
1339
1386
require .NoError (t , bc .VerifyTx (tx ))
1340
1387
})
1388
+ t .Run ("SystemFeeRefundableAttribute" , func (t * testing.T ) {
1389
+ tx := newTestTx (t , h , testScript , transaction.Attribute {Type : transaction .RefundableSystemFeeT , Value : & transaction.RefundableSystemFee {}})
1390
+ require .NoError (t , accs [0 ].SignTx (netmode .UnitTestNet , tx ))
1391
+ checkErr (t , core .ErrTxSmallNetworkFee , tx )
1392
+ tx .NetworkFee += bc .SystemFeeRefundCost ()
1393
+ require .Nil (t , bc .VerifyTx (tx ))
1394
+ t .Log ("success" )
1395
+ })
1341
1396
t .Run ("Oracle" , func (t * testing.T ) {
1342
1397
cs := contracts .GetOracleContractState (t , pathToInternalContracts , validator .ScriptHash (), 0 )
1343
1398
e .DeployContract (t , & neotest.Contract {
0 commit comments