github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/engine_nrc20_test.go (about)

     1  package nvm
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/big"
     8  	"testing"
     9  
    10  	"github.com/nebulasio/go-nebulas/consensus/dpos"
    11  	"github.com/nebulasio/go-nebulas/core"
    12  	"github.com/nebulasio/go-nebulas/core/state"
    13  	"github.com/nebulasio/go-nebulas/storage"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestERC20(t *testing.T) {
    18  	tests := []struct {
    19  		name         string
    20  		contractPath string
    21  		sourceType   string
    22  		initArgs     string
    23  		totalSupply  string
    24  	}{
    25  		{"deploy ERC20.js", "./test/ERC20.js", "js", "[\"TEST001\", \"TEST\", 1000000000]", "1000000000"},
    26  	}
    27  
    28  	// TODO: Addd more test cases
    29  	for _, tt := range tests {
    30  		t.Run(tt.name, func(t *testing.T) {
    31  			data, err := ioutil.ReadFile(tt.contractPath)
    32  			assert.Nil(t, err, "contract path read error")
    33  
    34  			mem, _ := storage.NewMemoryStorage()
    35  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
    36  			owner, err := context.GetOrCreateUserAccount([]byte("account1"))
    37  			assert.Nil(t, err)
    38  			owner.AddBalance(newUint128FromIntWrapper(10000000))
    39  			contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil)
    40  
    41  			ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context)
    42  			engine := NewV8Engine(ctx)
    43  			engine.SetExecutionLimits(10000, 10000000)
    44  			_, err = engine.DeployAndInit(string(data), tt.sourceType, tt.initArgs)
    45  			assert.Nil(t, err)
    46  			engine.Dispose()
    47  
    48  			engine = NewV8Engine(ctx)
    49  			engine.SetExecutionLimits(10000, 10000000)
    50  			_, err = engine.Call(string(data), tt.sourceType, "totalSupply", "[]")
    51  			assert.Nil(t, err)
    52  			engine.Dispose()
    53  
    54  		})
    55  	}
    56  }
    57  
    58  func TestNRC20Contract(t *testing.T) {
    59  	type TransferTest struct {
    60  		to     string
    61  		result bool
    62  		value  string
    63  	}
    64  
    65  	tests := []struct {
    66  		test          string
    67  		contractPath  string
    68  		sourceType    string
    69  		name          string
    70  		symbol        string
    71  		decimals      int
    72  		totalSupply   string
    73  		from          string
    74  		transferTests []TransferTest
    75  	}{
    76  		{"nrc20", "./test/NRC20.js", "js", "StandardToken标准代币", "ST", 18, "1000000000",
    77  			"n1FkntVUMPAsESuCAAPK711omQk19JotBjM",
    78  			[]TransferTest{
    79  				{"n1FkntVUMPAsESuCAAPK711omQk19JotBjM", true, "5"},
    80  				{"n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR", true, "10"},
    81  				{"n1Kjom3J4KPsHKKzZ2xtt8Lc9W5pRDjeLcW", true, "15"},
    82  			},
    83  		},
    84  	}
    85  
    86  	for _, tt := range tests {
    87  		t.Run(tt.name, func(t *testing.T) {
    88  			data, err := ioutil.ReadFile(tt.contractPath)
    89  			assert.Nil(t, err, "contract path read error")
    90  
    91  			mem, _ := storage.NewMemoryStorage()
    92  			context, _ := state.NewWorldState(dpos.NewDpos(), mem)
    93  			owner, err := context.GetOrCreateUserAccount([]byte(tt.from))
    94  			assert.Nil(t, err)
    95  			owner.AddBalance(newUint128FromIntWrapper(10000000))
    96  
    97  			// prepare the contract.
    98  			contractAddr, err := core.AddressParse(contractStr)
    99  			contract, _ := context.CreateContractAccount(contractAddr.Bytes(), nil, nil)
   100  			contract.AddBalance(newUint128FromIntWrapper(5))
   101  
   102  			// parepare env, block & transactions.
   103  			tx := mockNormalTransaction(tt.from, "n1TV3sU6jyzR4rJ1D7jCAmtVGSntJagXZHC", "0")
   104  			ctx, err := NewContext(mockBlock(), tx, contract, context)
   105  
   106  			// execute.
   107  			engine := NewV8Engine(ctx)
   108  			engine.SetExecutionLimits(10000, 100000000)
   109  			args := fmt.Sprintf("[\"%s\", \"%s\", %d, \"%s\"]", tt.name, tt.symbol, tt.decimals, tt.totalSupply)
   110  			_, err = engine.DeployAndInit(string(data), tt.sourceType, args)
   111  			assert.Nil(t, err)
   112  			engine.Dispose()
   113  
   114  			// call name.
   115  			engine = NewV8Engine(ctx)
   116  			engine.SetExecutionLimits(10000, 100000000)
   117  			name, err := engine.Call(string(data), tt.sourceType, "name", "")
   118  			assert.Nil(t, err)
   119  			var nameStr string
   120  			err = json.Unmarshal([]byte(name), &nameStr)
   121  			assert.Nil(t, err)
   122  			assert.Equal(t, tt.name, nameStr)
   123  			engine.Dispose()
   124  
   125  			// call symbol.
   126  			engine = NewV8Engine(ctx)
   127  			engine.SetExecutionLimits(10000, 100000000)
   128  			symbol, err := engine.Call(string(data), tt.sourceType, "symbol", "")
   129  			assert.Nil(t, err)
   130  			var symbolStr string
   131  			err = json.Unmarshal([]byte(symbol), &symbolStr)
   132  			assert.Nil(t, err)
   133  			assert.Equal(t, tt.symbol, symbolStr)
   134  			assert.Nil(t, err)
   135  			engine.Dispose()
   136  
   137  			// call decimals.
   138  			engine = NewV8Engine(ctx)
   139  			engine.SetExecutionLimits(10000, 100000000)
   140  			decimals, err := engine.Call(string(data), tt.sourceType, "decimals", "")
   141  			assert.Nil(t, err)
   142  			var decimalsInt int
   143  			err = json.Unmarshal([]byte(decimals), &decimalsInt)
   144  			assert.Nil(t, err)
   145  			assert.Equal(t, tt.decimals, decimalsInt)
   146  			assert.Nil(t, err)
   147  			engine.Dispose()
   148  
   149  			// call totalSupply.
   150  			engine = NewV8Engine(ctx)
   151  			engine.SetExecutionLimits(10000, 100000000)
   152  			totalSupply, err := engine.Call(string(data), tt.sourceType, "totalSupply", "")
   153  			assert.Nil(t, err)
   154  			var totalSupplyStr string
   155  			err = json.Unmarshal([]byte(totalSupply), &totalSupplyStr)
   156  			assert.Nil(t, err)
   157  			expect, _ := big.NewInt(0).SetString(tt.totalSupply, 10)
   158  			expect = expect.Mul(expect, big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(tt.decimals)), nil))
   159  			assert.Equal(t, expect.String(), totalSupplyStr)
   160  			assert.Nil(t, err)
   161  			engine.Dispose()
   162  
   163  			// call takeout.
   164  			for _, tot := range tt.transferTests {
   165  				// call balanceOf.
   166  				ctx.tx = mockNormalTransaction(tt.from, "n1TV3sU6jyzR4rJ1D7jCAmtVGSntJagXZHC", "0")
   167  				engine = NewV8Engine(ctx)
   168  				engine.SetExecutionLimits(10000, 100000000)
   169  				balArgs := fmt.Sprintf("[\"%s\"]", tt.from)
   170  				_, err := engine.Call(string(data), tt.sourceType, "balanceOf", balArgs)
   171  				assert.Nil(t, err)
   172  				engine.Dispose()
   173  
   174  				engine = NewV8Engine(ctx)
   175  				engine.SetExecutionLimits(10000, 100000000)
   176  				transferArgs := fmt.Sprintf("[\"%s\", \"%s\"]", tot.to, tot.value)
   177  				result, err := engine.Call(string(data), tt.sourceType, "transfer", transferArgs)
   178  				assert.Nil(t, err)
   179  				assert.Equal(t, "\"\"", result)
   180  				engine.Dispose()
   181  
   182  				engine = NewV8Engine(ctx)
   183  				engine.SetExecutionLimits(10000, 100000000)
   184  				approveArgs := fmt.Sprintf("[\"%s\", \"0\", \"%s\"]", tot.to, tot.value)
   185  				result, err = engine.Call(string(data), tt.sourceType, "approve", approveArgs)
   186  				assert.Nil(t, err)
   187  				assert.Equal(t, "\"\"", result)
   188  				engine.Dispose()
   189  
   190  				engine = NewV8Engine(ctx)
   191  				engine.SetExecutionLimits(10000, 100000000)
   192  				allowanceArgs := fmt.Sprintf("[\"%s\", \"%s\"]", tt.from, tot.to)
   193  				amount, err := engine.Call(string(data), tt.sourceType, "allowance", allowanceArgs)
   194  				assert.Nil(t, err)
   195  				var amountStr string
   196  				err = json.Unmarshal([]byte(amount), &amountStr)
   197  				assert.Nil(t, err)
   198  				assert.Equal(t, tot.value, amountStr)
   199  				engine.Dispose()
   200  
   201  				ctx.tx = mockNormalTransaction(tot.to, "n1TV3sU6jyzR4rJ1D7jCAmtVGSntJagXZHC", "0")
   202  				engine = NewV8Engine(ctx)
   203  				engine.SetExecutionLimits(10000, 100000000)
   204  				transferFromArgs := fmt.Sprintf("[\"%s\", \"%s\", \"%s\"]", tt.from, tot.to, tot.value)
   205  				result, err = engine.Call(string(data), tt.sourceType, "transferFrom", transferFromArgs)
   206  				assert.Nil(t, err)
   207  				assert.Equal(t, "\"\"", result)
   208  				engine.Dispose()
   209  
   210  				ctx.tx = mockNormalTransaction(tot.to, "n1TV3sU6jyzR4rJ1D7jCAmtVGSntJagXZHC", "0")
   211  				engine = NewV8Engine(ctx)
   212  				engine.SetExecutionLimits(10000, 100000000)
   213  				transferFromArgs = fmt.Sprintf("[\"%s\", \"%s\", \"%s\"]", tt.from, tot.to, tot.value)
   214  				_, err = engine.Call(string(data), tt.sourceType, "transferFrom", transferFromArgs)
   215  				assert.NotNil(t, err)
   216  				engine.Dispose()
   217  			}
   218  		})
   219  	}
   220  }
   221  
   222  func TestNRC20ContractMultitimes(t *testing.T) {
   223  	for i := 0; i < 5; i++ {
   224  		TestNRC20Contract(t)
   225  	}
   226  }