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 }