neo-go/pkg/core/native_gas_test.go
Anna Shaleva e8bed184d5 core: implement dynamic NEP17 balances tracking
Request NEP17 balances from a set of NEP17 contracts instead of getting
them from storage. LastUpdatedBlock tracking remains untouched, because
there's no way to retrieve it dynamically.
2021-07-29 10:23:01 +03:00

115 lines
4.4 KiB
Go

package core
import (
"math/big"
"testing"
"github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/require"
)
func TestGAS_Refuel(t *testing.T) {
bc := newTestChain(t)
cs, _ := getTestContractState(bc)
require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs))
const (
sysFee = 10_000000
burnFee = sysFee + 12345678
)
accs := []*wallet.Account{
newAccountWithGAS(t, bc),
newAccountWithGAS(t, bc),
}
t.Run("good, refuel from self", func(t *testing.T) {
before0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
aer, err := invokeContractMethodGeneric(bc, sysFee, bc.contracts.GAS.Hash, "refuel",
accs[0], accs[0].Contract.ScriptHash(), int64(burnFee))
require.NoError(t, err)
require.Equal(t, vm.HaltState, aer.VMState)
after0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
tx, _, _ := bc.GetTransaction(aer.Container)
require.Equal(t, before0, new(big.Int).Add(after0, big.NewInt(tx.SystemFee+tx.NetworkFee+burnFee)))
})
t.Run("good, refuel from other", func(t *testing.T) {
before0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
before1 := bc.GetUtilityTokenBalance(accs[1].Contract.ScriptHash())
aer, err := invokeContractMethodGeneric(bc, sysFee, cs.Hash, "refuelGas",
accs, accs[1].Contract.ScriptHash(), int64(burnFee), int64(burnFee))
require.NoError(t, err)
require.Equal(t, vm.HaltState, aer.VMState)
after0 := bc.GetUtilityTokenBalance(accs[0].Contract.ScriptHash())
after1 := bc.GetUtilityTokenBalance(accs[1].Contract.ScriptHash())
tx, _, _ := bc.GetTransaction(aer.Container)
require.Equal(t, before0, new(big.Int).Add(after0, big.NewInt(tx.SystemFee+tx.NetworkFee)))
require.Equal(t, before1, new(big.Int).Add(after1, big.NewInt(burnFee)))
})
t.Run("bad, invalid witness", func(t *testing.T) {
aer, err := invokeContractMethodGeneric(bc, sysFee, cs.Hash, "refuelGas",
accs, random.Uint160(), int64(1), int64(1))
require.NoError(t, err)
require.Equal(t, vm.FaultState, aer.VMState)
})
t.Run("bad, invalid GAS amount", func(t *testing.T) {
aer, err := invokeContractMethodGeneric(bc, sysFee, cs.Hash, "refuelGas",
accs, accs[0].Contract.ScriptHash(), int64(0), int64(1))
require.NoError(t, err)
require.Equal(t, vm.FaultState, aer.VMState)
})
}
func TestGAS_Roundtrip(t *testing.T) {
bc := newTestChain(t)
getUtilityTokenBalance := func(bc *Blockchain, acc util.Uint160) (*big.Int, uint32) {
lub, err := bc.GetNEP17LastUpdated(acc)
require.NoError(t, err)
return bc.GetUtilityTokenBalance(acc), lub[bc.contracts.GAS.ID]
}
initialBalance, _ := getUtilityTokenBalance(bc, neoOwner)
require.NotNil(t, initialBalance)
t.Run("bad: amount > initial balance", func(t *testing.T) {
tx := transferTokenFromMultisigAccountWithAssert(t, bc, neoOwner, bc.contracts.GAS.Hash, initialBalance.Int64()+1, false)
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err)
require.Equal(t, vm.HaltState, aer[0].VMState, aer[0].FaultException) // transfer without assert => HALT state
checkResult(t, &aer[0], stackitem.NewBool(false))
require.Len(t, aer[0].Events, 0) // failed transfer => no events
// check balance and height were not changed
updatedBalance, updatedHeight := getUtilityTokenBalance(bc, neoOwner)
initialBalance.Sub(initialBalance, big.NewInt(tx.SystemFee+tx.NetworkFee))
require.Equal(t, initialBalance, updatedBalance)
require.Equal(t, bc.BlockHeight(), updatedHeight)
})
t.Run("good: amount < initial balance", func(t *testing.T) {
amount := initialBalance.Int64() - 10_00000000
tx := transferTokenFromMultisigAccountWithAssert(t, bc, neoOwner, bc.contracts.GAS.Hash, amount, false)
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err)
require.Equal(t, vm.HaltState, aer[0].VMState, aer[0].FaultException)
checkResult(t, &aer[0], stackitem.NewBool(true))
require.Len(t, aer[0].Events, 1) // roundtrip
// check balance wasn't changed and height was updated
updatedBalance, updatedHeight := getUtilityTokenBalance(bc, neoOwner)
initialBalance.Sub(initialBalance, big.NewInt(tx.SystemFee+tx.NetworkFee))
require.Equal(t, initialBalance, updatedBalance)
require.Equal(t, bc.BlockHeight(), updatedHeight)
})
}